Menu
Lumberyard
Legacy Reference

Creating Flow Graph Nodes

Flow Graph is deprecated and will be removed in a future version of Lumberyard. Learn about Script Canvas, Lumberyard's new visual scripting environment.

This topic references tools and features that are legacy. If you want to use legacy tools in Lumberyard Editor, disable the CryEntity Removal gem using the Project Configurator or the command line. To learn about the latest features, see the Amazon Lumberyard User Guide.

You can use a .cpp file to create new flow graph nodes. For multiple flow graph nodes that will belong to the same group, use a single .cpp file. Headers aren't needed except for some specialized nodes.

Use the following code template for your .cpp file and save the file to the dev\Code\CryEngine\CryAction\FlowSystem\Nodes directory.

In the template you can choose between an eNCT_Instanced node and a eNCT_Singleton. A singleton node creates one instance with a small memory footprint, although you can still use multiple nodes in your flow graph. Use singleton whenever you are not saving state data such as member variables.

#include "StdAfx.h" #include "FlowBaseNode.h" class CFlowNode_your_flow_node_name : public CFlowBaseNode<eNCT_Instanced> { public: CFlowNode_your_flow_node_name(SActivationInfo* pActInfo) { }; virtual IFlowNodePtr Clone(SActivationInfo *pActInfo) { return new CFlowNode_your_flow_node_name(pActInfo); }; virtual void GetMemoryUsage(ICrySizer* s) const { s->Add(*this); } virtual void GetConfiguration(SFlowNodeConfig& config) { static const SInputPortConfig in_config[] = { {0} }; static const SOutputPortConfig out_config[] = { {0} }; config.sDescription = _HELP( "your_flow_node_tooltip_description" ); config.pInputPorts = in_config; config.pOutputPorts = out_config; config.SetCategory(EFLN_APPROVED); } virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo) { switch (event) { }; } }; REGISTER_FLOW_NODE("your_flow_node_group:your_flow_node_name", CFlowNode_your_flow_node_name);

For your flow node group, create a corresponding subfolder in the Flow Graph editor node selector where this node will be placed in the hierarchy.

Output Ports

You can add an output port by modifying the GetConfiguration function as shown in the following example:

class CFlowNode_your_flow_node_name : public CFlowBaseNode<eNCT_Instanced> { public: // ... virtual void GetConfiguration( SFlowNodeConfig& config ) { static const SInputPortConfig in_config[] = { {0} }; static const SOutputPortConfig out_config[] = { OutputPortConfig<int>("your_output", _HELP("your_help_text")), {0} }; config.sDescription = _HELP( "your_flow_node_tooltip_description" ); config.pInputPorts = in_config; config.pOutputPorts = out_config; config.nFlags = 0; } // ... };

OutputPortConfig is a helper function that is useful for filling a small structure with appropriate data.

Available data types for this function include SFlowSystemVoid, Int, Float, EntityId, Vec3, String, and Bool. SFlowSystemVoid is a special data type that represents "no value".

OutputPortConfig takes the following parameters:

  • Port name that is used internally and for saving the flow graph. Do not change this parameter later as doing so will break script compatibility for all flow graphs that use this node.

    Note

    Do not use the underscore "_" character as this was used in previous versions to specify a specialized editor for the port.

  • Description used to display tooltip help text on mouse hover in the Flow Graph editor.

  • Human-readable name used to display the name of the port in the Flow Graph editor. This is used to visually override a port name without breaking script compatibility.

To emit a value from the output port, use the function CFlowBaseNode::ActivateOutput(pActInfo, nPort, value). This function takes a pActInfo, which is typically passed to ProcessEvent(), the nPort port identifier (count starts at zero from the top of out_config), and a value of the same type as the port.

Input Ports

You can add an input port by modifying the GetConfiguration function as shown in the following example:

class CFlowNode_your_flow_node_name : public CFlowBaseNode<eNCT_Instanced> { public: // ... virtual void GetConfiguration( SFlowNodeConfig& config ) { static const SInputPortConfig in_config[] = { InputPortConfig<int>("your_input", _HELP("your_help_text")), {0} }; static const SOutputPortConfig out_config[] = { {0} }; config.sDescription = _HELP( "your_flow_node_tooltip_description" ); config.pInputPorts = in_config; config.pOutputPorts = out_config; config.nFlags = 0; } // ... };

InputPortConfig is a helper function that is useful for filling a small structure with appropriate data.

Available data types for this function include SFlowSystemVoid, Int, Float, EntityId, Vec3, String, and Bool. SFlowSystemVoid is a special data type that represents "no value".

InputPortConfig takes the following parameters:

  • Port name used internally and for saving the flow graph. Do not change this parameter later as doing so will break script compatibility for all flow graphs that use this node.

    Note

    Do not use the underscore "_" character as this was used in previous versions to specify a specialized editor for the port.

  • Default value of the port when a new node is created.

  • Description used to display tooltip help text on mouse hover in the Flow Graph editor.

  • Human-readable name used to display the name of the port in the Flow Graph editor. Use to visually override a port name without breaking script compatibility.

  • Formatted string that specifies how the UI should function when setting the port value. You can choose a specialized widget or modify the allowed value range of the input.

Input Port UI Configuration

You can define the interface for setting the input port value by passing a series of options in the form of a string with key–value pairs in InputPortConfig.

Setting the input value range

This will limit the widget's arrows and ramp and clamp manually-inserted values as shown in the figure:

_UICONFIG("v_min=0, v_max=10")

Setting the Drop-down List

There are several types of enums that you can use to display a drop-down list of readable strings. Each string maps to a value that is used by the node and that persists when the flow graph is saved. Enums can be of type int or float as shown in the following figure and code example.

_UICONFIG("enum_int:Relaxed=0,Alert=1,Combat=2,Crouch=3")

An enum can also be of type string with or without mapping to another value:

_UICONFIG("enum_string:a,b,c") _UICONFIG("enum_string:DisplayA=a,DisplayB=b,DisplayC=c")

Enums can also refer to the global and dynamic UI enums defined in InitUIEnums.

Optionally, the enum can depend on another port to affect the available selection:

_UICONFIG("enum_global:ENUM_NAME") _UICONFIG("enum_global:vehicleLightTypes") _UICONFIG("enum_global_def:ENUM_NAME") _UICONFIG("enum_global_ref:ENUM_NAME_FORMAT_STRING:REF_PORT")

Setting a Specialized Property Editor

You can indicate a dedicated property editor with the dt keyword followed by parameters optionally needed by the editor as shown in the following code example:

_UICONFIG("dt=editorName")_UICONFIG("dt=entityProperties, ref_entity=entityId") _UICONFIG("dt=matparamslot, slot_ref=Slot, sub_ref=SubMtlId, param=float")

There is a set of available editors that can be referenced in the following table:

Editor Name Editor Type
snd IVariable::DT_SOUND
sound IVariable::DT_SOUND
clr IVariable::DT_COLOR
color IVariable::DT_COLOR
tex IVariable::DT_TEXTURE
texture IVariable::DT_TEXTURE
obj IVariable::DT_OBJECT
object IVariable::DT_OBJECT
file IVariable::DT_FILE
text IVariable::DT_LOCAL_STRING
equip IVariable::DT_EQUIP
reverbpreset IVariable::DT_REVERBPRESET
aianchor IVariable::DT_AI_ANCHOR
aibehavior IVariable::DT_AI_BEHAVIOR
aicharacter IVariable::DT_AI_CHARACTER
aipfpropertieslist IVariable::DT_AI_PFPROPERTIESLIST
aientityclasses IVariable::DT_AIENTITYCLASSES
soclass IVariable::DT_SOCLASS
soclasses IVariable::DT_SOCLASSES
sostate IVariable::DT_SOSTATE
sostates IVariable::DT_SOSTATES
sopattern IVariable::DT_SOSTATEPATTERN
soaction IVariable::DT_SOACTION
sohelper IVariable::DT_SOHELPER
sonavhelper IVariable::DT_SONAVHELPER
soanimhelper IVariable::DT_SOANIMHELPER
soevent IVariable::DT_SOEVENT
customaction IVariable::DT_CUSTOMACTION
gametoken IVariable::DT_GAMETOKEN
mat IVariable::DT_MATERIAL
seq IVariable::DT_SEQUENCE
mission IVariable::DT_MISSIONOBJ
anim IVariable::DT_USERITEMCB
animstate IVariable::DT_USERITEMCB
animstateEx IVariable::DT_USERITEMCB
bone IVariable::DT_USERITEMCB
attachment IVariable::DT_USERITEMCB
dialog IVariable::DT_USERITEMCB
matparamslot IVariable::DT_USERITEMCB
matparamname IVariable::DT_USERITEMCB
matparamcharatt IVariable::DT_USERITEMCB
seqid IVariable::DT_SEQUENCE_ID
lightanimation IVariable::DT_LIGHT_ANIMATION
formation IVariable::DT_USERITEMCB
communicationVariable IVariable::DT_USERITEMCB
uiElements IVariable::DT_USERITEMCB
uiActions IVariable::DT_USERITEMCB
uiVariables IVariable::DT_USERITEMCB
uiArrays IVariable::DT_USERITEMCB
uiMovieclips IVariable::DT_USERITEMCB
uiVariablesTmpl IVariable::DT_USERITEMCB
uiArraysTmpl IVariable::DT_USERITEMCB
uiMovieclipsTmpl IVariable::DT_USERITEMCB
uiTemplates IVariable::DT_USERITEMCB
vehicleParts IVariable::DT_USERITEMCB
vehicleSeatViews IVariable::DT_USERITEMCB
entityProperties IVariable::DT_USERITEMCB
actionFilter IVariable::DT_USERITEMCB
actionMaps IVariable::DT_USERITEMCB
actionMapActions IVariable::DT_USERITEMCB
geomcache IVariable::DT_GEOM_CACHE
audioTrigger IVariable::DT_AUDIO_TRIGGER
audioSwitch IVariable::DT_AUDIO_SWITCH
audioSwitchState IVariable::DT_AUDIO_SWITCH_STATE
audioRTPC IVariable::DT_AUDIO_RTPC
audioEnvironment IVariable::DT_AUDIO_ENVIRONMENT
audioPreloadRequest IVariable::DT_AUDIO_PRELOAD_REQUEST
dynamicResponseSignal IVariable::DT_DYNAMIC_RESPONSE_SIGNAL

Trigger Ports

It can be useful to have a trigger signal as an input or output port. You can implement these ports using the Input/OutputPortConfig_Void or Input/OutputPortConfig_AnyType data types. Do not use the Boolean data type.

Update Event

If you want an update loop for your node instead of having it react on ports, you can use the following code to add your node to the list of regularly updated nodes. You can also choose to enable the update event temporarily.

The following code adds your node to the list of regularly updated nodes:

pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, true);

You will get a single ProcessEvent(eFE_Updated) call per game update call.

To remove it from this list, call the same function with false as the second parameter.