Token导航 LogoToken导航TokenDH.com
前端设计操作浏览器github未标认证来源可访问许可证需确认审计通过

vvvv-custom-nodesvvvv 自定义节点

Agent Skill

vvvv-custom-nodes 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

979

周安装

40

GitHub Stars

23

下载量

314
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:vvvv-custom-nodes(vvvv 自定义节点)
来源仓库:https://github.com/tebjan/vvvv-skills
仓库路径:skills/vvvv-custom-nodes
安装命令:
npx skills add https://github.com/tebjan/vvvv-skills --skill vvvv-custom-nodes
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/tebjan/vvvv-skills --skill vvvv-custom-nodes

简介

用于处理 vvvv 自定义节点的 XML 注释与引脚配置,辅助前端设计开发。

  • 适用于 Codex、Claude、Cursor 等宿主中生成节点定义与参数说明。
  • 支持自动生成节点名称、分类与引脚可见性设置。
  • 安装命令:npx skills add https://github.com/tebjan/vvvv-skills --skill vvvv-custom-nodes。
  • 注意:涉及代码生成时应核对命名规范与程序集属性匹配情况。

SKILL.md

Writing Custom Nodes for vvvv gamma

What [ProcessNode] actually does (and what it does NOT do)

Important reality check. vvvv imports every public class, struct, enum, method, and property from the assembly's configured namespaces — [ProcessNode] does NOT control whether a class becomes a node. A plain public class Foo {public int Bar(int x) => x;} will appear in the node browser exactly the same way as one decorated with [ProcessNode]. The attribute affects *how* the runtime treats the class, not *whether* it gets imported.

What [ProcessNode] DOES:

  • Tells vvvv "this is a stateful node — keep ONE instance alive per node in the patch and call its Update() method each frame".
  • Lets you set Name = "..." (rename for the node browser), Category = "..." (override the assembly's category), and HasStateOutput = true (expose the instance as an output pin).
  • Engages live reload, IDisposable cleanup, and the NodeContext constructor injection.

What [ProcessNode] does NOT do:

  • It does NOT make a class visible to vvvv. Visibility comes from the C# public access modifier plus an [assembly: ImportAsIs/ImportNamespace/ImportType] attribute. See vvvv-node-libraries for the import rules.
  • It does NOT hide internal helpers. If a helper is public, it's a node — period. Use internal to hide.
  • It does NOT change pin generation. Pin generation is driven by the Update() method signature for [ProcessNode] classes, and by public method/property signatures for non-[ProcessNode] classes.

When to use [ProcessNode]: the class needs frame-by-frame updates, persistent state between frames, or IDisposable cleanup. When to skip [ProcessNode]: stateless utility classes, value types, static helper methods — leaving the attribute off avoids the per-frame Update() ceremony, and the public methods become operation nodes automatically.

ProcessNode Pattern — The Core Pattern

The canonical stateful C# node in vvvv gamma:

[ProcessNode]
public class MyTransform : IDisposable
{
    private float _lastInput;
    private float _cachedResult;

    /// <summary>
    /// Transforms input values with caching.
    /// </summary>
    public void Update(
        out float result,       // OUT parameters FIRST
        out string error,       // More out params
        float input = 0f,       // Value inputs with defaults AFTER
        bool reset = false)
    {
        error = null;

        if (input != _lastInput || reset)
        {
            _cachedResult = ExpensiveComputation(input);
            _lastInput = input;
        }

        result = _cachedResult; // ALWAYS output cached data
    }

    public void Dispose() { /* cleanup */ }
}

Prerequisite: vvvv only sees a [ProcessNode] class (or any other public class) if its namespace is covered by an assembly-level import attribute — [assembly: ImportAsIs], [assembly: ImportNamespace], or [assembly: ImportType] for that specific class. Without one of those, the assembly's public API is invisible to the node browser entirely. Projects scaffolded by vvvv include [assembly: ImportAsIs] automatically. For multi-namespace libraries or hand-picked node lists, see vvvv-node-libraries — ImportAsIs is AllowMultiple = false, so you'll reach for ImportNamespace (multi-use) or ImportType (per-type) when one root attribute isn't enough.

Non-Negotiable Rules

  1. [ProcessNode] attribute on every stateful node class
  2. No "Node" in the vvvv-visible name — everything in vvvv is already a node, so "Node" suffix is redundant
  3. out parameters FIRST, value inputs with defaults AFTER
  4. XML comments on class and Update method (shown as tooltip in vvvv)
  5. ZERO allocations in Update — no new, no LINQ, cache everything
  6. Change detection — only recompute when inputs actually change
  7. Always output latest data — even when no work is done, output cached result
  8. No unnecessary public members — data flows through Update in/out params only
  9. IDisposable for any node holding native/unmanaged resources

Live Reload Behavior

When the.vl document references a.csproj source project, vvvv compiles C# via Roslyn at runtime. On.cs file save, vvvv recompiles and restarts affected nodes:

  1. Dispose() is called on the current instance (if IDisposable)
  2. The new constructor runs with a fresh NodeContext
  3. Update() resumes on the next frame

Implications for node authors:

  • Instance fields reset — any state accumulated during runtime (caches, counters, connections) is lost on code change. This is expected.
  • Static fields also reset — the entire in-memory assembly is replaced. Do not rely on static state to survive edits.
  • Dispose must be thorough — native handles, network connections, and GPU resources must be released. Leaks accumulate across reloads during development.
  • Constructor must be fast — it runs each time you save. Defer heavy initialization to the first Update() call using a _needsInit flag.
  • The rules about caching and change detection above exist partly because of this: your code runs in a program that never stops. Allocations in Update() cause GC pressure in a 60 FPS loop that may run for hours.

Class Naming vs Node Name

The rule is: users must never see "Node" in vvvv's node browser. How you achieve this:

// Simple: class name IS the node name — no suffix needed
[ProcessNode]
public class Wander { }              // vvvv shows: "Wander"

// Class has "Node" suffix + Name property strips it — also fine
[ProcessNode(Name = "Scan")]
public class ScanNode { }            // vvvv shows: "Scan"

// Completely different internal name — fine when class manages another type
[ProcessNode(Name = "MeshRenderer", Category = "Stride.Rendering.Custom")]
public class CustomMeshRenderer { }  // vvvv shows: "MeshRenderer"

HasStateOutput — Exposing Node Instance

[ProcessNode(HasStateOutput = true)]
public class ParticleSystem
{
    // The node itself becomes an output pin,
    // allowing downstream nodes to call methods on it
    public void Update(out int particleCount, ...) { ... }
}

Alternative: return this from a method to expose the instance.

Pin Visibility

public void Update(
    out Spread<float> result,
    [Pin(Visibility = PinVisibility.OnlyInspector)] out string error,
    float input = 0f,
    [Pin(Visibility = PinVisibility.Optional)] bool advanced = false)
{
    // PinVisibility values:
    // Visible       — always shown (default)
    // Optional      — user can show/hide
    // Hidden        — not visible, only via inspector
    // OnlyInspector — only in inspector panel (use for debug/error outputs)
}

Pin Groups (Collection Inputs)

For Spread inputs with add/remove buttons in vvvv:

public void Update(
    out float result,
    [Pin(Name = "Input", PinGroupKind = PinGroupKind.Collection, PinGroupDefaultCount = 2)]
    Spread<IRenderer?> input)
{ }

DefaultValue for Complex Types

For defaults that cannot be C# literal expressions:

public void Update(
    [DefaultValue(typeof(Color4), "0.1, 0.1, 0.15, 1.0")] Color4 clearColor,
    [DefaultValue(typeof(Int2), "1920, 1080")] Int2 size,
    bool clear = true)
{ }

Attributes — when you actually need them

Verified against VL.StandardLibs/VL.Core/src/Import/ source. Most attribute properties have sensible defaults — set them only when you want to override the default. Setting an attribute property to its default value is just visual noise.

[ProcessNode] — class-level (AllowMultiple = false)

PropertyDefaultSet it when…
NameC# class name…the node's user-facing name should differ from the class name. If Name would equal the class name, omit it.
Categoryfrom assembly-level import attribute…you want this specific class to land in a different category than the rest of the assembly.
HasStateOutputfalse…downstream nodes need access to the node instance itself (e.g. to call methods on it).
FragmentSelectionImplicit (all public members become fragments)…you want only members marked [Fragment] to be exposed.
StateOutputNotVisibleByDefaultfalse…you have a state output but want it hidden until the user enables it.
Summary, Remarks, TagsnullThese are alternatives to XML doc comments; prefer the comments unless you need programmatic access.

So [ProcessNode] (bare) is the right default for the common case where the class name = node name and category falls out of the assembly attribute. Adding [ProcessNode(Name = "Foo", Category = "Bar")] is only useful when those values diverge from what the defaults would produce.

[Pin] — parameter / property / return-value (AllowMultiple = false)

PropertyDefaultSet it when…
Namethe parameter name (vvvv applies title-casing automatically)…you need a name vvvv can't derive — e.g. spaces, punctuation, or a name unrelated to the parameter. [Pin(Name = "input")] on a parameter input is redundant — vvvv already shows it as Input.
VisibilityPinVisibility.Visible…you want the pin Optional (collapsible) or Hidden (inspector-only).
ExpositionPinExpositionMode.Local…you want the pin auto-exposed on parent patches (InfectPatch / Expose).
PinGroupKindPinGroupKind.None…the parameter is a Spread<T> that should appear as an add/remove pin group.
PinGroupDefaultCount0…a pin group should start with N entries.
PinGroupEditModeNone…you want to limit add/remove to one direction only.

The return value attribute ([return: Pin(...)]) is only needed when the auto-derived return-value pin needs an override — e.g. a custom name. The default name is fine for nearly all Update methods that only have out parameters.

[DefaultValue] — parameter (from System.ComponentModel)

NOT a vvvv attribute. Set it only for value types where the literal isn't expressible as a C# default — Color4, Vector3, Int2, etc. For int, float, bool, string, prefer the C# parameter default (int x = 5).

⚠️ Never combine [DefaultValue(...)] with = default on the same parameter — the C# default wins and your typed default becomes black/zero/null. See the dedicated section above.

[Fragment] — member-level (AllowMultiple = false)

Only relevant when [ProcessNode(FragmentSelection = FragmentSelection.Explicit)] is set on the class. With the default Implicit selection, [Fragment] is unnecessary noise.

PropertyDefaultSet it when…
Order0 (declaration order)…you need a specific fragment order independent of source layout.
IsHiddenfalse…a member should NOT become a fragment despite being public.
IsDefaultfalse…this fragment should run at the default moment when nothing else is wired.

Rule of thumb

  1. If the attribute has only default values, don't write the attribute.
  2. If you only need ONE non-default property, write only that one (e.g. [Pin(Visibility = PinVisibility.Optional)]).
  3. The presence of an attribute should always communicate "I'm overriding a default", never "I'm restating the default".

Constructor Patterns

Simple node (no special context):

public MyNode() { }

Node needing NodeContext (for AppHost, services, Fuse shader graphs):

public MyNode(NodeContext nodeContext)
{
    _nodeContext = nodeContext;
    // Access: nodeContext.AppHost.IsExported, nodeContext.AppHost.Services, etc.
}

For IFrameClock injection, Stride Game access, logging, and service consumption patterns, see services.md.

Change Detection Patterns

Simple — Direct Field Comparison

private float _lastParam;
private Result _cached;

public void Update(out Result result, float param = 0f)
{
    if (param != _lastParam)
    {
        _cached = Compute(param);
        _lastParam = param;
    }
    result = _cached;
}

Multi-Input — Hash Check

private int _lastHash;
private Config _cached;

public void Update(out Config config, float a = 0f, int b = 0, string c = "")
{
    int hash = HashCode.Combine(a, b, c);
    if (hash != _lastHash)
    {
        _cached = new Config(a, b, c);
        _lastHash = hash;
    }
    config = _cached;
}

Reference Types — Identity Check

if (!ReferenceEquals(newBuffer, _lastBuffer))
{
    ProcessBuffer(newBuffer);
    _lastBuffer = newBuffer;
}

Rebuild Flag — For Pipeline/Effect State

When multiple setters can invalidate state:

private bool _needsRebuild = true;

public void SetShader(ShaderStage vs) { _shader = vs; _needsRebuild = true; }

public void Update(out Effect effect)
{
    if (_needsRebuild)
    {
        RebuildPipeline();
        _needsRebuild = false;
    }
    effect = _cachedEffect;
}

Quick Reference

Input TypeComparisonNotes
Value types (int, float, bool)!=Direct comparison
Reference types (objects)ReferenceEquals()Identity, not equality
Multiple inputsHashCode.Combine()Single hash for dirty check
CollectionsLength + sample elementsFull comparison too expensive
Multiple setters_needsRebuild flagSet flag in setters, check in Update

Return-Based Output (Single Output)

When a node has a single primary output, you can return it directly instead of using out:

[ProcessNode]
public class NoiseSteering
{
    private SteeringConfig? _cached;

    public ISteering Update(
        float strength = 2.0f,
        float noiseFrequency = 0.05f,
        int priority = 0)
    {
        if (_cached is null || _cached.Strength != strength ||
            _cached.NoiseFrequency != noiseFrequency || _cached.Priority != priority)
        {
            _cached = new SteeringConfig(strength, noiseFrequency, priority);
        }
        return _cached;
    }
}

Mix return + out when you have one primary output plus additional outputs:

public ReadOnlySpan<ParticleState> Update(
    SimulationConfig config,
    float deltaTime,
    out TimingStats stats)  // Secondary output via out
{
    // Returns primary output, secondary via out
}

Rising Edge Detection (Bang/Trigger)

For boolean inputs that should trigger once (not every frame they're true):

private bool _lastTrigger;

public void Update(out bool triggered, bool trigger = false)
{
    triggered = trigger && !_lastTrigger; // Rising edge only
    _lastTrigger = trigger;
}

Operation Nodes

vvvv auto-generates nodes from all public C# methods — no attribute needed. Don't create [ProcessNode] wrappers for simple methods that just forward calls. Struct Split() methods also become nodes automatically.

Static methods auto-generate nodes — no [ProcessNode] needed:

public static class MathOps
{
    public static float Remap(float value, float inMin = 0f, float inMax = 1f,
                              float outMin = 0f, float outMax = 1f)
    {
        float t = (value - inMin) / (inMax - inMin);
        return outMin + t * (outMax - outMin);
    }
}

When to Use Which

PatternUse When
[ProcessNode] classManages state between frames, caching, dirty-checking
Static methodPure function, no state, transforms input to output
Struct + Split()Data containers that unpack into separate pins

Memory & Performance in Update Loop

  • No new keyword in hot paths
  • No LINQ (.Where, .Select, .ToList) — hidden allocations via enumerators
  • Cache collections — pre-allocate, reuse arrays/lists
  • No string concatenation — use StringBuilder if needed, but avoid in hot path
  • Vector types: System.Numerics internally for SIMD, Stride.Core.Mathematics at API boundaries
  • Zero-cost conversion: Unsafe.As<StrideVector3, NumericsVector3>(ref val)

For custom regions (delegate-based, ICustomRegion, IRegion<TInlay>), see regions.md. For advanced patterns (FragmentSelection, Smell, Dynamic Enums, Settings/Split, Pin Name Derivation), see advanced.md. For service consumption (IFrameClock, Game, Logging), see services.md. For working with public channels from C# nodes, see vvvv-channels. For code examples, see examples.md. For starter templates, see templates/.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

33.36%
按下载量换算105

Claude

31.59%
按下载量换算99

Cursor

18.48%
按下载量换算58

Gemini CLI

9.71%
按下载量换算30

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills