FlowCanvas Forums › Support › Macro from code
Hello,
Is it somehow possible to ‘call’ a macro from code, giving it input and getting output ? treating it like a function(s) that can be called from script ?
Basically like a data provider.
Asim.
Hello and very sorry for the late reply!
While techically it is possible, there is not API to make it easy. With that said you can add these lines of code into Macro.cs somewhere so that this can be done easier.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/// Set a value input of type T of the Macro to a certain value. /// Only use to interface with the Macro from code. public void SetValueInput<T>(string name, T value) { var def = inputDefinitions.FirstOrDefault(d => d.name == name && d.type == typeof(T)); if ( def == null ) { ParadoxNotion.Services.Logger.LogError(string.Format("Input of name {0} and type {1}, does not exist within the list of Macro Inputs", name, typeof(T)), "Execution", entry); return; } entryFunctionMap[def.ID] = () => { return value; }; } /// Call a Flow Input of the Macro. /// Only use to interface with the Macro from code. public void CallFlowInput(string name) { var def = inputDefinitions.FirstOrDefault(d => d.name == name && d.type == typeof(Flow)); if ( def == null ) { ParadoxNotion.Services.Logger.LogError(string.Format("Input of name {0} and type Flow, does not exist within the list of Macro Inputs", name), "Execution", entry); return; } entryActionMap[def.ID](new Flow()); } /// Get the value output of type T of the Macro. /// Only use to interface with the Macro from code. public T GetValueOutput<T>(string name) { var def = outputDefinitions.FirstOrDefault(d => d.name == name && d.type == typeof(T)); if ( def == null ) { ParadoxNotion.Services.Logger.LogError(string.Format("Input of name {0} and type {1} do not exist within the list of Macro Outputs", name, typeof(T)), "Execution", exit); return default(T); } return (T)exitFunctionMap[def.ID](); } |
With these lines of code in there, you will then be able to use a Macro and either Set one of it’s Value Inputs, Call one of it’s Flow Inputs, or Get one of it’s Value Outputs from code. Remember though, that you will need to instantiate the Macro asset and call StartGraph to the instance. Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class MacroFromCode : MonoBehaviour { public Macro macroAsset; private Macro macroInstance; void Awake() { macroInstance = Instantiate(macroAsset); macroInstance.StartGraph(null, null, false); } void Update() { if ( Input.GetKeyDown(KeyCode.Space) ) { macroInstance.CallFlowInput("In"); Debug.Log(macroInstance.GetValueOutput<float>("someValue")); } } } |
With all that said though, Macros can still not be treated exactly like a Function would, since a Macro can have multiple Value as well as Flow outputs and as such it is implemented to work differently than a function would.
other alternative you may want to consider, is to actually use a “Custom Function” setup (in the browser -> “Function/Custom/New Custom Function”) which work similar to how a usual code function would and can also be invoked from code via the “CallFunction” method.
For this alternative, you dont really need a Macro Asset, but a FlowScript Asset would be preferable since the inputs and outputs of the Macro does not matter.
Thus what I would recommend doing, is to create a FlowScript Asset as normal and create a Custom Function within that FlowScript, like this example:
Then from within your code, instantiate the flowScript asset and call “StartGraph” on it’s instance. Finally call “CallFunction” on the instannce wherever is required. Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class MacroFromCode : MonoBehaviour { public FlowScript flowScriptAsset; private FlowScript flowScriptInstance; void Awake() { flowScriptInstance = Instantiate(flowScriptAsset); flowScriptInstance.StartGraph(null, null, false); } void Update() { if ( Input.GetKeyDown(KeyCode.Space) ) { var functionResult = flowScriptInstance.CallFunction<float>("MyFunction", 2f, 3f); Debug.Log(functionResult); } } } |
You can of course have any number of Custom Functions implemented within the flowScript.
Please let me know if any of two options above work for you, or if you need any more information or help.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh