Skip to main content

Command Creator Window

Opening a Command Creator Window

Making a command, especially the complex one, would be quite tiring with all the boilerplates.

In that case, Sequine also provides a Command Creator Window that can help generating a Command script using a window with a user-friendly GUI to visualize how the generated command would look like.

It can only generate scripts that handles the drawings, so that we can focus more on the behaviour of the command.

To open the window, from the menu bar, click Tools -> Sequine -> Command Creator...

Command Creator Window

Creating an Example Command

Let's try to create a command as an example!

Example Command

We can save/load the configuration template as well. Upon saving the template, it will create a json file.

Here's the json output for the example command above. You can paste this in a json file, and load it using the Load Template... button.

ExampleCommand.json
{"displayName":"Custom/Example Command","tooltip":"This is a new example command.","nodeWidth":250.0,"isPropertyCommand":false,"titleHasOutPoint":true,"lines":[{"contentType":0,"label":"My Integer","tooltip":"","pointLocation":1,"pointType":0,"outMainType":0,"alignRight":false,"fieldType":5,"lineCount":2,"wordWrap":true,"useMin":true,"useMax":false,"min":0.0,"max":0.0,"allowSceneObjects":true,"spacing":0.0},{"contentType":1,"label":"My String Output","tooltip":"","pointLocation":2,"pointType":4,"outMainType":0,"alignRight":true,"fieldType":5,"lineCount":2,"wordWrap":true,"useMin":true,"useMax":false,"min":0.0,"max":0.0,"allowSceneObjects":true,"spacing":0.0},{"contentType":1,"label":"My Alternative Exit","tooltip":"","pointLocation":2,"pointType":0,"outMainType":0,"alignRight":true,"fieldType":5,"lineCount":2,"wordWrap":true,"useMin":true,"useMax":false,"min":0.0,"max":0.0,"allowSceneObjects":true,"spacing":0.0},{"contentType":1,"label":"My Parallel Output","tooltip":"","pointLocation":2,"pointType":0,"outMainType":1,"alignRight":true,"fieldType":5,"lineCount":2,"wordWrap":true,"useMin":true,"useMax":false,"min":0.0,"max":0.0,"allowSceneObjects":true,"spacing":0.0}],"className":"ExampleCommand","_namespace":"MyNamespace","includedCommandData":[{"name":"Level Command Data","include":false},{"name":"Sequine Flow Command Data","include":true}]}

To generate the actual command script, we can click the Generate Script... button.

Here's how the generated script looks like.

ExampleCommand.cs
using Calcatz.CookieCutter;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MyNamespace {

[System.Serializable]
[RegisterCommand("Custom/Example Command", typeof(Calcatz.Sequine.SequineFlowCommandData))]
public class ExampleCommand : Command {

public override void Execute(CommandExecutionFlow _flow) {
var myInteger_value = GetInput<System.Int32>(_flow, IN_PORT_MY_INTEGER, myInteger);

//....................................
//...YOUR EXECUTION LOGIC GOES HERE...
//....................................

RunSubFlow(_flow, OUT_PORT_MY_PARALLEL_OUTPUT);
Exit();
}

public override T GetOutput<T>(CommandExecutionFlow _flow, int _pointIndex) {
switch(_pointIndex) {

case OUT_PORT_MY_STRING_OUTPUT:
//...YOUR EVALUATION LOGIC GOES HERE...
return (T)(object)"";

default:
Debug.LogError("Output port index does not exist in ExampleCommand: " + _pointIndex);
return default(T);
}
}

public override int GetNextOutputIndex() {
//You can change exitPortIndex in Execute method by your desired condition
return exitPortIndex;
}

#region PROPERTIES

private int exitPortIndex = 0;

public override float nodeWidth => 250f;

private const int IN_PORT_MY_INTEGER = 0;

private const int OUT_PORT_MY_STRING_OUTPUT = 1;
private const int OUT_PORT_MY_ALTERNATIVE_EXIT = 2;
private const int OUT_PORT_MY_PARALLEL_OUTPUT = 3;

public System.Int32 myInteger;
#endregion PROPERTIES

#region NODE-DRAWER
#if UNITY_EDITOR
public override void Editor_InitInPoints() {
CommandGUI.AddMainInPoint();
if (inputIds.Count <= IN_PORT_MY_INTEGER) {
inputIds.Add(new ConnectionTarget());
}
CommandGUI.AddPropertyInPoint<System.Int32>();
}

public override void Editor_InitOutPoints() {
CommandGUI.AddMainOutPoint();
if (nextIds.Count <= OUT_PORT_MY_STRING_OUTPUT) {
nextIds.Add(new List<ConnectionTarget>());
}
if (nextIds.Count <= OUT_PORT_MY_ALTERNATIVE_EXIT) {
nextIds.Add(new List<ConnectionTarget>());
}
if (nextIds.Count <= OUT_PORT_MY_PARALLEL_OUTPUT) {
nextIds.Add(new List<ConnectionTarget>());
}
CommandGUI.AddPropertyOutPoint<System.String>();
CommandGUI.AddMainOutPoint();
CommandGUI.AddMainOutPoint();
}

public override void Editor_OnDrawTitle(out string _tooltip) {
_tooltip = @"This is a new example command.";
CommandGUI.DrawInPoint(0);
CommandGUI.DrawOutPoint(0);
}

public override void Editor_OnDrawContents(Vector2 _absPosition) {
CommandGUI.DrawInPoint(IN_PORT_MY_INTEGER + 1);
if (inputIds[IN_PORT_MY_INTEGER].targetId == 0) {
CommandGUI.DrawIntField("My Integer", "", ref myInteger, 0);
}
else {
CommandGUI.DrawLabel("My Integer");
}
CommandGUI.DrawOutPoint(OUT_PORT_MY_STRING_OUTPUT);
CommandGUI.DrawLabel("My String Output", true);
CommandGUI.DrawOutPoint(OUT_PORT_MY_ALTERNATIVE_EXIT);
CommandGUI.DrawLabel("My Alternative Exit", true);
CommandGUI.DrawOutPoint(OUT_PORT_MY_PARALLEL_OUTPUT);
CommandGUI.DrawLabel("My Parallel Output", true);
}

#endif
#endregion NODE-DRAWER

}

}

We see that it generated all the boilerplates for us. What's left for us to do is to write the actual functionality in some methods such as Execute, GetOutput, and GetNextOutputIndex.

We dont have to mind anything inside the PROPERTIES and NODE-DRAWER regions.