Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/Sources/armory/logicnode/CallFunctionNode.hx b/Sources/armory/logicnode/CallFunctionNode.hx
- index d53fabae..b032dd95 100644
- --- a/Sources/armory/logicnode/CallFunctionNode.hx
- +++ b/Sources/armory/logicnode/CallFunctionNode.hx
- @@ -15,8 +15,15 @@ class CallFunctionNode extends LogicNode {
- if (object == null) return;
- var funName:String = inputs[2].get();
- + var args:Array<Dynamic> = [];
- +
- + for (i in 3...inputs.length) {
- + args.push(inputs[i].get());
- + }
- - result = Reflect.callMethod(object, Reflect.field(object, funName), null);
- + var func = Reflect.field(object, funName);
- + if (func != null)
- + result = Reflect.callMethod(object, func, args);
- runOutputs(0);
- }
- diff --git a/Sources/armory/logicnode/FunctionNode.hx b/Sources/armory/logicnode/FunctionNode.hx
- new file mode 100644
- index 00000000..65950224
- --- /dev/null
- +++ b/Sources/armory/logicnode/FunctionNode.hx
- @@ -0,0 +1,22 @@
- +package armory.logicnode;
- +
- +class FunctionNode extends LogicNode {
- +
- + @:allow(armory.logicnode.LogicTree)
- + var args:Array<Dynamic> = [];
- + @:allow(armory.logicnode.LogicTree)
- + var result:Dynamic;
- +
- + public function new(tree:LogicTree) {
- + super(tree);
- + }
- +
- + @:allow(armory.logicnode.LogicTree)
- + override function run(from:Int) {
- + runOutput(0);
- + }
- +
- + override function get(from:Int) {
- + return this.args[from - 1];
- + }
- +}
- diff --git a/Sources/armory/logicnode/FunctionOutputNode.hx b/Sources/armory/logicnode/FunctionOutputNode.hx
- new file mode 100644
- index 00000000..1a10722c
- --- /dev/null
- +++ b/Sources/armory/logicnode/FunctionOutputNode.hx
- @@ -0,0 +1,16 @@
- +package armory.logicnode;
- +
- +class FunctionOutputNode extends LogicNode {
- +
- + @:allow(armory.logicnode.LogicTree)
- + var result:Dynamic;
- +
- + public function new(tree:LogicTree) {
- + super(tree);
- + }
- +
- + override function run(from:Int) {
- + this.result = inputs[1].get();
- + runOutput(0);
- + }
- +}
- diff --git a/blender/arm/logicnode/action_call_function.py b/blender/arm/logicnode/action_call_function.py
- new file mode 100644
- index 00000000..7eab4d65
- --- /dev/null
- +++ b/blender/arm/logicnode/action_call_function.py
- @@ -0,0 +1,33 @@
- +import bpy
- +from bpy.props import *
- +from bpy.types import Node, NodeSocket
- +from arm.logicnode.arm_nodes import *
- +
- +class CallFunctionNode(Node, ArmLogicTreeNode):
- + '''Call Haxe function node'''
- + bl_idname = 'LNCallFunctionNode'
- + bl_label = 'Call Function'
- + bl_icon = 'GAME'
- + min_inputs = 3
- +
- + def __init__(self):
- + array_nodes[str(id(self))] = self
- +
- + def init(self, context):
- + self.inputs.new('ArmNodeSocketAction', 'In')
- + self.inputs.new('NodeSocketShader', 'Trait/Any')
- + self.inputs.new('NodeSocketString', 'Function')
- + self.outputs.new('ArmNodeSocketAction', 'Out')
- + self.outputs.new('NodeSocketShader', 'Result')
- +
- + def draw_buttons(self, context, layout):
- + row = layout.row(align=True)
- + op = row.operator('arm.node_add_input', text='Add Arg', icon='PLUS', emboss=True)
- + op.node_index = str(id(self))
- + op.socket_type = 'NodeSocketShader'
- + op.name_format = "Arg {0}"
- + op.index_name_offset = -2
- + op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
- + op2.node_index = str(id(self))
- +
- +add_node(CallFunctionNode, category='Action')
- diff --git a/blender/arm/logicnode/arm_nodes.py b/blender/arm/logicnode/arm_nodes.py
- index db257d68..eb43cc24 100644
- --- a/blender/arm/logicnode/arm_nodes.py
- +++ b/blender/arm/logicnode/arm_nodes.py
- @@ -122,11 +122,13 @@ class ArmNodeAddInputButton(bpy.types.Operator):
- bl_label = 'Add Input'
- node_index = StringProperty(name='Node Index', default='')
- socket_type = StringProperty(name='Socket Type', default='NodeSocketShader')
- + name_format = StringProperty(name='Name Format', default='Input {0}')
- + index_name_offset = IntProperty(name='Index Name Offset', default=0)
- def execute(self, context):
- global array_nodes
- inps = array_nodes[self.node_index].inputs
- - inps.new(self.socket_type, 'Input ' + str(len(inps)))
- + inps.new(self.socket_type, self.name_format.format(str(len(inps) + self.index_name_offset)))
- return{'FINISHED'}
- class ArmNodeAddInputValueButton(bpy.types.Operator):
- @@ -178,11 +180,13 @@ class ArmNodeAddOutputButton(bpy.types.Operator):
- bl_label = 'Add Output'
- node_index = StringProperty(name='Node Index', default='')
- socket_type = StringProperty(name='Socket Type', default='NodeSocketShader')
- + name_format = StringProperty(name='Name Format', default='Output {0}')
- + index_name_offset = IntProperty(name='Index Name Offset', default=0)
- def execute(self, context):
- global array_nodes
- outs = array_nodes[self.node_index].outputs
- - outs.new(self.socket_type, 'Output ' + str(len(outs)))
- + outs.new(self.socket_type, self.name_format.format(str(len(outs) + self.index_name_offset)))
- return{'FINISHED'}
- class ArmNodeRemoveOutputButton(bpy.types.Operator):
- diff --git a/blender/arm/logicnode/logic_function.py b/blender/arm/logicnode/logic_function.py
- new file mode 100644
- index 00000000..6e5cb9ea
- --- /dev/null
- +++ b/blender/arm/logicnode/logic_function.py
- @@ -0,0 +1,33 @@
- +import bpy
- +from bpy.props import *
- +from bpy.types import Node, NodeSocket
- +from arm.logicnode.arm_nodes import *
- +
- +class FunctionNode(Node, ArmLogicTreeNode):
- + '''Function node'''
- + bl_idname = 'LNFunctionNode'
- + bl_label = 'Function'
- + bl_icon = 'CURVE_PATH'
- + min_outputs = 1
- +
- + def __init__(self):
- + array_nodes[str(id(self))] = self
- +
- + def init(self, context):
- + self.outputs.new('ArmNodeSocketAction', 'Out')
- +
- + function_name = StringProperty(name="Name")
- +
- + def draw_buttons(self, context, layout):
- + row = layout.row(align=True)
- + row.prop(self, 'function_name')
- + row = layout.row(align=True)
- + op = row.operator('arm.node_add_output', text='Add Arg', icon='PLUS', emboss=True)
- + op.node_index = str(id(self))
- + op.socket_type = 'NodeSocketShader'
- + op.name_format = "Arg {0}"
- + op.index_name_offset = 0
- + op2 = row.operator('arm.node_remove_output', text='', icon='X', emboss=True)
- + op2.node_index = str(id(self))
- +
- +add_node(FunctionNode, category='Logic')
- diff --git a/blender/arm/logicnode/logic_function_output.py b/blender/arm/logicnode/logic_function_output.py
- new file mode 100644
- index 00000000..dfc5fd90
- --- /dev/null
- +++ b/blender/arm/logicnode/logic_function_output.py
- @@ -0,0 +1,22 @@
- +import bpy
- +from bpy.props import *
- +from bpy.types import Node, NodeSocket
- +from arm.logicnode.arm_nodes import *
- +
- +class FunctionOutputNode(Node, ArmLogicTreeNode):
- + '''Function output node'''
- + bl_idname = 'LNFunctionOutputNode'
- + bl_label = 'Function Output'
- + bl_icon = 'CURVE_PATH'
- +
- + def init(self, context):
- + self.inputs.new('ArmNodeSocketAction', 'In')
- + self.inputs.new('NodeSocketShader', 'Value')
- +
- + function_name = StringProperty(name="Name")
- +
- + def draw_buttons(self, context, layout):
- + row = layout.row(align=True)
- + row.prop(self, 'function_name')
- +
- +add_node(FunctionOutputNode, category='Logic')
- diff --git a/blender/arm/make_logic.py b/blender/arm/make_logic.py
- index 833cba1b..72beb9b4 100755
- --- a/blender/arm/make_logic.py
- +++ b/blender/arm/make_logic.py
- @@ -6,6 +6,8 @@ from arm.exporter import ArmoryExporter
- parsed_nodes = []
- parsed_ids = dict() # Sharing node data
- +function_nodes = dict()
- +function_node_outputs = dict()
- group_name = ''
- def get_logic_trees():
- @@ -32,9 +34,13 @@ def build():
- def build_node_tree(node_group):
- global parsed_nodes
- global parsed_ids
- + global function_nodes
- + global function_node_outputs
- global group_name
- parsed_nodes = []
- parsed_ids = dict()
- + function_nodes = dict()
- + function_node_outputs = dict()
- root_nodes = get_root_nodes(node_group)
- pack_path = arm.utils.safestr(bpy.data.worlds['Arm'].arm_project_package)
- @@ -54,15 +60,39 @@ def build_node_tree(node_group):
- with open(file, 'w') as f:
- f.write('package ' + pack_path + '.node;\n\n')
- f.write('@:keep class ' + group_name + ' extends armory.logicnode.LogicTree {\n\n')
- - f.write('\tpublic function new() { super();')
- + f.write('\tvar functionNodes:Map<String, armory.logicnode.FunctionNode>;\n\n')
- + f.write('\tvar functionOutputNodes:Map<String, armory.logicnode.FunctionOutputNode>;\n\n')
- + f.write('\tpublic function new() {\n')
- + f.write('\t\tsuper();\n')
- if bpy.data.worlds['Arm'].arm_play_console:
- - f.write(' name = "' + group_name + '";')
- - f.write(' notifyOnAdd(add); }\n\n')
- + f.write('\t\tname = "' + group_name + '";\n')
- + f.write('\t\tthis.functionNodes = new Map();\n')
- + f.write('\t\tthis.functionOutputNodes = new Map();\n')
- + f.write('\t\tnotifyOnAdd(add);\n')
- + f.write('\t}\n\n')
- f.write('\toverride public function add() {\n')
- for node in root_nodes:
- build_node(node, f)
- f.write('\t}\n')
- - f.write('}\n')
- +
- + # Create node functions
- + for node_name in function_nodes:
- + node = function_nodes[node_name]
- + function_name = node.function_name
- + f.write('\n\tpublic function ' + function_name + '(')
- + for i in range(0, len(node.outputs) - 1):
- + if i != 0: f.write(', ')
- + f.write('arg' + str(i) + ':Dynamic')
- + f.write(') {\n')
- + f.write('\t\tvar functionNode = this.functionNodes["' + node_name + '"];\n')
- + f.write('\t\tfunctionNode.args = [];\n')
- + for i in range(0, len(node.outputs) - 1):
- + f.write('\t\tfunctionNode.args.push(arg' + str(i) + ');\n')
- + f.write('\t\tfunctionNode.run(0);\n')
- + if function_node_outputs.get(function_name) != None:
- + f.write('\t\treturn this.functionOutputNodes["' + function_node_outputs[function_name] + '"].result;\n')
- + f.write('\t}\n\n')
- + f.write('}')
- node_group.is_cached = True
- def build_node(node, f):
- @@ -94,6 +124,15 @@ def build_node(node, f):
- node_type = node.bl_idname[2:] # Discard 'LN'TimeNode prefix
- f.write('\t\tvar ' + name + ' = new armory.logicnode.' + node_type + '(this);\n')
- + # Handle Function Nodes
- + if node_type == 'FunctionNode':
- + f.write('\t\tthis.functionNodes.set("' + name + '", ' + name + ');\n')
- + function_nodes[name] = node
- + elif node_type == 'FunctionOutputNode':
- + f.write('\t\tthis.functionOutputNodes.set("' + name + '", ' + name + ');\n')
- + # Index function output name by corresponding function name
- + function_node_outputs[node.function_name] = name
- +
- # Watch in debug console
- if node.arm_watch and bpy.data.worlds['Arm'].arm_play_console:
- f.write('\t\t' + name + '.name = "' + name[1:] + '";\n')
Add Comment
Please, Sign In to add comment