deargui-vpl/docs/llm/create-blocks.md
2026-02-03 18:25:25 +01:00

3.3 KiB

Creating Blocks Programmatically

This guide provides a concise overview of how to add and configure block nodes programmatically in a command-line or testing environment. This is essential for creating automated unit tests. We assume a working App instance is available, as set up in headless mode (see main.cpp).

Process Overview

Creating and connecting a block involves several steps:

  1. Get Active Container: Obtain a pointer to the current RootContainer from the App instance.
  2. Spawn Nodes: Create the necessary nodes. For example, to use a Log block, you need to spawn the Log block itself and also any parameter nodes that will provide its inputs (like the file path).
  3. Configure Parameter Nodes: Set the values for the parameter nodes you've created.
  4. Connect Nodes: Find the corresponding input and output pins on the nodes and create a Link to connect them.
  5. Set Positions (Optional): If you plan to save the graph for visual inspection, set the node positions using ed::SetNodePosition().
  6. Save Graph: Persist the changes by calling App::SaveGraph(), passing the container and a file path.

Example: Creating and Connecting a Log Block

The following function demonstrates adding a "Log" block, providing its required "FilePath" input via a "String" parameter node, connecting them, and saving the graph.

#include "app.h"
#include "containers/root_container.h"
#include "blocks/parameter_node.h" // Required for ParameterInstance

// Assumes 'app' is an initialized App instance
void AddAndConnectLogBlock(App& app, const std::string& logFilePath, const std::string& savePath)
{
    // 1. Get container
    RootContainer* container = app.GetActiveRootContainer();
    if (!container)
        return;

    // 2. Spawn the log block and a parameter node for the file path
    Node* logNode = app.SpawnBlockNode("Log", -1);
    Node* pathNode = app.SpawnParameterNode(PinType::String, -1);
    if (!logNode || !pathNode)
        return;

    // 3. Configure the parameter node's value
    pathNode->StringValue = logFilePath;
    if (pathNode->ParameterInstance) {
        pathNode->ParameterInstance->SetString(logFilePath.c_str());
    }

    // 4. Connect the nodes
    // The String parameter node has one output.
    Pin* pathOutputPin = &pathNode->Outputs[0];
    
    // The Log block's 'FilePath' is its first non-flow input pin.
    // Input[0] is 'Execute' (flow), Input[1] is 'FilePath'.
    Pin* logInputPin = nullptr;
    if (logNode->Inputs.size() > 1) {
        logInputPin = &logNode->Inputs[1];
    }

    if (pathOutputPin && logInputPin)
    {
        Link newLink(app.GetNextLinkId(), pathOutputPin->ID, logInputPin->ID);
        container->AddLink(newLink);
    }

    // 5. Set positions (optional, requires an editor context)
    ed::SetNodePosition(logNode->ID, ImVec2(200.0f, 100.0f));
    ed::SetNodePosition(pathNode->ID, ImVec2(0.0f, 100.0f));

    // 6. Save the updated graph
    app.SaveGraph(savePath, container);
}

This more detailed example provides a solid foundation for scripting graph creation for unit tests, ensuring that blocks are not only created but also correctly configured and connected.

Block Reference

For a complete list of available blocks and their parameters, see the Block Reference.