Node to Code Documentation

repository·main·Indexed 20 days ago

https://github.com/protospatial/nodetocode

An Unreal Engine plugin that uses Large Language Models (LLMs) to translate visual Blueprint graphs into structured C++, C#, JavaScript, Python, Swift, or pseudocode. It features a custom N2C JSON schema to reduce token usage, support for local LLMs via Ollama and LM Studio, and integration with cloud providers like OpenAI, Anthropic Claude, Google Gemini, and DeepSeek.

Tokens
8K
Snippets
10
Records
22
Agent score
72%

What's inside Node to Code

  1. Overview of Node to Code capabilities

    main

    Node to Code is an LLM-powered Unreal Engine plugin designed to transform Blueprint graphs into structured code (C++, C#, JavaScript, Python, Swift) or pseudocode.

    Key features include:

    • Blueprint Translation: Converts execution flows, data connections, and variable references into text-based code.
    • Architecture Navigation: Captures Blueprint hierarchies with configurable depth (up to 5 levels).
    • Local LLM Support: Run translations 100% locally using Ollama for privacy, or use LM Studio.
    • Cloud LLM Support: Integration with OpenAI, Anthropic Claude, Google Gemini, and DeepSeek.
    • Style Guidance: You can provide your own C++ files as reference to ensure the generated code follows your project's specific coding standards.
    • Efficient Serialization: Uses a custom JSON schema to reduce token usage by 60-90% compared to standard Unreal Blueprint text formats.
  2. Implement Blueprint Logic Flow in Python

    main

    To faithfully replicate Blueprint execution and data flow in Python, use the following patterns:

    1. Execution Flow (Exec Pins)

    Use the flows.execution array (e.g., "N1->N2->N3") to determine the order of Python statements.

    • Branch: Convert to a Python if statement.
    • Sequence: Execute statements sequentially.
    • DoOnce: Use a state variable (static, global, or class member) to track execution.
    • ForLoop: Use for i in range(start, end+1):.
    • ForEachLoop: Use for element in container: or for index, element in enumerate(container):.
    • Gate: Use a state variable to allow or prevent execution.

    2. Data Flow (Data Pins)

    • If a connection exists from N1.P5 to N2.P2, pass the value from N1 as an argument or variable to N2 in Python.
    • Use default_value from pins as literal values in Python.

    3. Node Types

    • CallFunction: Generate a function call (e.g., KismetSystemLibrary::PrintString $\rightarrow$ print()).
    • VariableSet: Generate a Python assignment (x = value).
    • VariableGet: Reference the variable's value.
    • Pure Nodes: Implement as expressions or pure function calls (no sequential execution flow required).
    • Latent Nodes: Optionally use async def to represent asynchronous operations.
  3. Understand the Node to Code (N2C) JSON Specification

    main

    The Node to Code (N2C) JSON format (FN2CBlueprint serialized) is the input format used to represent Unreal Engine 4/5 Blueprint logic. It describes the structural flow and data connections of a Blueprint so they can be translated into other languages like JavaScript.

    Key JSON Components

    • metadata: Contains the Blueprint's Name, BlueprintType (e.g., Normal, MacroLibrary, Interface), and the BlueprintClass (the corresponding UClass).
    • graphs: An array of graph objects. Each graph contains:
      • nodes: An array of node objects. Each node has an id, type (e.g., CallFunction, VariableSet, VariableGet, Event), name, and details about its input_pins and output_pins.
      • flows: Defines the logic sequence.
        • execution: An array of strings representing the execution order (e.g., "N1->N2->N3").
        • data: A map representing data-flow connections (e.g., "N1.P2": "N2.P1").
    • structs: An optional array defining custom structures and their members.
    • enums: An optional array defining enumerations and their possible values.

    Pin Details

    Each pin in a node includes:

    • type: The data type (e.g., Exec, Boolean, Integer, String, Object).
    • default_value: The literal value if provided.
    • connected: Boolean indicating if the pin is linked.
    • is_reference, is_const, is_array, is_map, is_set: Boolean flags for the pin's nature.
    {
      "version": "1.0.0",
      "metadata": {
        "Name": "MyBlueprint",
        "BlueprintType": "Normal",
        "BlueprintClass": "MyCharacter"
      },
      "graphs": [
        {
          "name": "ExecuteMyFunction",
          "graph_type": "Function",
          "nodes": [
            {
              "id": "N1",
              "type": "CallFunction",
              "name": "Print String",
              "member_parent": "KismetSystemLibrary",
              "member_name": "PrintString",
              "input_pins": [
                { "id": "P1", "name": "Exec", "type": "Exec", "connected": true },
                { "id": "P2", "name": "InString", "type": "String", "default_value": "Hello from NodeToCode" }
              ],
              "output_pins": [
                { "id": "P3", "name": "Then", "type": "Exec", "connected": true }
              ]
            }
          ],
          "flows": {
            "execution": ["N1->N2->N3"],
            "data": {"N1.P2": "N2.P1"}
          }
        }
      ]
    }
  4. Replicate Blueprint Logic Flow in C#

    main

    To ensure functional parity, translate Blueprint flow macro nodes into their C# equivalents:

    • Branch $\rightarrow$ if/else statements.
    • Sequence $\rightarrow$ Sequential statements in order.
    • DoOnce $\rightarrow$ A private bool guard/check.
    • ForLoop $\rightarrow$ for loop.
    • ForEachLoop $\rightarrow$ foreach loop.
    • Gate $\rightarrow$ A bool toggle to allow/prevent execution.
    • Delay $\rightarrow$ A Unity Coroutine using yield return new WaitForSeconds(...).
  5. Translate Blueprint Logic to Swift Code

    main

    When converting N2C JSON to Swift, follow these translation rules to maintain the structural integrity of the original Blueprint logic:

    1. Graph Type Mapping

    • Function: Convert to a standalone Swift function.
    • EventGraph: Treat as a top-level Swift function or method that orchestrates calls.
    • Macro: Implement as a helper Swift function with parameters/returns.
    • Composite/Collapsed: Implement as an internal helper function or inline the logic.
    • Construction: Replicate the logic flow within a Swift function.
    • Struct/Enum: Generate separate graph objects with graph_type: "Struct" or "Enum".

    2. Node Translation

    • CallFunction: Map to a Swift function call (e.g., KismetSystemLibrary::PrintString $\rightarrow$ print()).
    • VariableSet: Map to a Swift assignment (=).
    • VariableGet: Map to a variable reference.
    • Event: Define the function signature.
    • pure nodes: Implement as expressions or pure function calls (no side effects).
    • latent nodes: Use async in Swift or note in implementation notes.

    3. Flow Control Emulation

    • Branch: Use Swift if statements.
    • Sequence: Execute statements in the order defined by the execution flow.
    • DoOnce: Use a static property or a class property to track state.
    • ForLoop / ForEachLoop: Use for i in start...end or for element in collection.
    • Gate: Use a boolean state variable to allow/prevent execution.

    4. Pin Handling

    • Exec Pins: Define the sequential order of operations.
    • Data Pins: Pass values from output pins to input pins as function arguments or variables.
  6. Convert N2C JSON to Unreal C++ Code

    main

    To transform N2C JSON into C++, follow these translation rules:

    1. Graph Translation

    • Function: Convert to a standalone C++ function.
    • EventGraph: Treat as an ExecuteUbergraph or entry point function.
    • Macro: Implement as a helper function with parameters/returns matching the macro's pins.
    • Composite/Collapsed: Inline the logic or generate an internal helper function.
    • Construction: Produce a function with relevant statements (noting editor-specific context).

    2. Node Translation

    • CallFunction: Use native Unreal C++ APIs (e.g., UKismetSystemLibrary::PrintString) instead of Blueprint K2 wrappers (e.g., use SetActorLocation instead of K2_SetActorLocation).
    • VariableSet/Get: Use standard C++ assignments or property references.
    • Event: Use the event to define the function signature or entry point.
    • Flow Macros:
      • Branch $\rightarrow$ if statements.
      • Sequence $\rightarrow$ Sequential code blocks.
      • DoOnce $\rightarrow$ Static or member boolean guard.
      • ForLoop/ForEachLoop $\rightarrow$ Standard or range-based C++ loops.
      • Gate $\rightarrow$ Boolean state machine/variable.

    3. Data and Flow

    • Exec Pins: Follow the flows.execution order (e.g., N1->N2 means N1 code then N2 code).
    • Data Pins: Pass values from source pins to destination pins using default_value or variable references.
    • Pure Nodes: Treat as expressions or inline function calls (no execution flow).
    • Latent Nodes: Call the function and note the async nature in implementation notes.
  7. Translate Blueprint Graphs to Python Functions

    main

    When converting N2C JSON to Python, follow these mapping rules for different graph types:

    • Function Graph (graph_type: "Function"): Convert into a standalone Python function.
    • Event Graph (graph_type: "EventGraph"): Treat as a main entry point or an orchestrating function.
    • Macro (graph_type: "Macro"): Implement as a helper Python function, mapping macro parameters to function arguments and outputs to return values.
    • Composite/Collapsed Graph (graph_type: "Composite"): Implement as an internal helper function or inline the logic.
    • Construction Script (graph_type: "Construction"): Replicate the logic flow within a Python function.
    • Struct (graph_type: "Struct"): Generate a Python class with attributes matching the struct members. The definition goes in graphDeclaration and the implementation in graphImplementation (though the implementation field should be empty for structs in the final output format).
    • Enum (graph_type: "Enum"): Use Python's enum.Enum class. The definition goes in graphDeclaration.
  8. Integrate Reference Source Files into Pseudocode

    main

    If the user provides reference source files (e.g., .h or .cpp files) within <referenceSourceFiles> tags, you must adjust the context of your pseudocode:

    1. Contextual Placement: Assume the pseudocode belongs in a location relevant to the original class or function described in the source files.
    2. Class Naming: If the source files specify a class name, use that name in your output instead of the name provided in the metadata.BlueprintClass field of the N2C JSON.
  9. Translate Blueprint Graphs to Unity C#

    main

    When converting N2C JSON to Unity C#, map the graph_type to the appropriate Unity/C# construct:

    Blueprint graph_typeUnity C# Implementation
    FunctionA standard C# method.
    EventGraphUnity MonoBehaviour event methods (e.g., Start(), Update()).
    MacroA utility method.
    CompositeA helper method or inline logic.
    ConstructionAwake() or Start() logic.
    StructA C# struct or class (use [System.Serializable] for Inspector visibility).
    EnumA standard C# enum.

    Node Translation Rules

    • CallFunction: Generate a Unity API call (e.g., Debug.Log()).
    • VariableSet: Generate a C# assignment (myVar = value;).
    • VariableGet: Reference a variable or property.
    • Event: Define a function signature or Unity event.
    • Data Types: Map Unreal types to Unity types (e.g., FString $\rightarrow$ string, FVector $\rightarrow$ Vector3, FRotator $\rightarrow$ Quaternion).
    • Containers: Map TArray $\rightarrow$ List<T>, TMap $\rightarrow$ Dictionary<K, V>.
  10. Install the Node to Code plugin

    main

    To use Node to Code in your Unreal Engine project, download the latest stable builds from the official Releases page. Once downloaded, install the plugin into your engine or specific project directory as per standard Unreal Engine plugin installation procedures.

    https://github.com/protospatial/NodeToCode/releases
  11. Configure local LLM via LM Studio

    main

    If you prefer to run your translations locally using LM Studio rather than a cloud provider, follow the dedicated Quick Start Guide to set up the connection between the plugin and your local LM Studio instance.

    https://github.com/protospatial/NodeToCode/wiki/LM-Studio-Quick-Start
  12. Translate Blueprints to JavaScript Code

    main

    When converting N2C JSON to JavaScript, follow these implementation steps to ensure the logic is faithfully represented:

    1. Interpret Graph Types

    Map the graph_type to the appropriate JavaScript structure:

    • Function: Convert to a standalone JavaScript function.
    • EventGraph: Treat as a main entry function that orchestrates other calls.
    • Macro: Implement as a helper function with parameters/returns matching the macro's pins.
    • Composite (Collapsed): Inline the logic or generate an internal helper function.
    • Construction: Convert to a JS function containing the relevant logic.

    2. Translate Nodes and Pins

    • CallFunction: Generate a JS function call (e.g., console.log() for PrintString).
    • VariableSet: Produce a JS assignment (x = value).
    • VariableGet: Reference the variable.
    • Event: Treat as the function entry point.
    • Pure Nodes: (where pure: true) Implement as inline expressions or direct function calls without execution flow.
    • Latent Nodes: (where latent: true) Use async/await in JavaScript.

    3. Implement Control Flow

    Use standard JavaScript control structures to replicate the flows property:

    • Branch: if (...) { ... } else { ... }
    • Sequence: Standard sequential statements.
    • DoOnce: Use a boolean state variable to track execution.
    • ForLoop: for (let i = start; i <= end; i++) { ... }
    • ForEachLoop: array.forEach(...) or for (const item of array) { ... }
    • Gate: Use a variable to allow/disallow execution.

    4. Handle Structs and Enums

    • Structs: Generate a graph object with graph_type: "Struct". Place the JS representation (e.g., a class or object literal) in graphDeclaration and leave graphImplementation empty.
    • Enums: Generate a graph object with graph_type: "Enum". Place the JS representation (e.g., a frozen object) in graphDeclaration and leave graphImplementation empty.