Guest User

Untitled

a guest
Nov 17th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.89 KB | None | 0 0
  1. diff --git a/Sources/armory/logicnode/CallFunctionNode.hx b/Sources/armory/logicnode/CallFunctionNode.hx
  2. index d53fabae..b032dd95 100644
  3. --- a/Sources/armory/logicnode/CallFunctionNode.hx
  4. +++ b/Sources/armory/logicnode/CallFunctionNode.hx
  5. @@ -15,8 +15,15 @@ class CallFunctionNode extends LogicNode {
  6. if (object == null) return;
  7.  
  8. var funName:String = inputs[2].get();
  9. + var args:Array<Dynamic> = [];
  10. +
  11. + for (i in 3...inputs.length) {
  12. + args.push(inputs[i].get());
  13. + }
  14.  
  15. - result = Reflect.callMethod(object, Reflect.field(object, funName), null);
  16. + var func = Reflect.field(object, funName);
  17. + if (func != null)
  18. + result = Reflect.callMethod(object, func, args);
  19.  
  20. runOutputs(0);
  21. }
  22. diff --git a/Sources/armory/logicnode/FunctionNode.hx b/Sources/armory/logicnode/FunctionNode.hx
  23. new file mode 100644
  24. index 00000000..65950224
  25. --- /dev/null
  26. +++ b/Sources/armory/logicnode/FunctionNode.hx
  27. @@ -0,0 +1,22 @@
  28. +package armory.logicnode;
  29. +
  30. +class FunctionNode extends LogicNode {
  31. +
  32. + @:allow(armory.logicnode.LogicTree)
  33. + var args:Array<Dynamic> = [];
  34. + @:allow(armory.logicnode.LogicTree)
  35. + var result:Dynamic;
  36. +
  37. + public function new(tree:LogicTree) {
  38. + super(tree);
  39. + }
  40. +
  41. + @:allow(armory.logicnode.LogicTree)
  42. + override function run(from:Int) {
  43. + runOutput(0);
  44. + }
  45. +
  46. + override function get(from:Int) {
  47. + return this.args[from - 1];
  48. + }
  49. +}
  50. diff --git a/Sources/armory/logicnode/FunctionOutputNode.hx b/Sources/armory/logicnode/FunctionOutputNode.hx
  51. new file mode 100644
  52. index 00000000..1a10722c
  53. --- /dev/null
  54. +++ b/Sources/armory/logicnode/FunctionOutputNode.hx
  55. @@ -0,0 +1,16 @@
  56. +package armory.logicnode;
  57. +
  58. +class FunctionOutputNode extends LogicNode {
  59. +
  60. + @:allow(armory.logicnode.LogicTree)
  61. + var result:Dynamic;
  62. +
  63. + public function new(tree:LogicTree) {
  64. + super(tree);
  65. + }
  66. +
  67. + override function run(from:Int) {
  68. + this.result = inputs[1].get();
  69. + runOutput(0);
  70. + }
  71. +}
  72. diff --git a/blender/arm/logicnode/action_call_function.py b/blender/arm/logicnode/action_call_function.py
  73. new file mode 100644
  74. index 00000000..7eab4d65
  75. --- /dev/null
  76. +++ b/blender/arm/logicnode/action_call_function.py
  77. @@ -0,0 +1,33 @@
  78. +import bpy
  79. +from bpy.props import *
  80. +from bpy.types import Node, NodeSocket
  81. +from arm.logicnode.arm_nodes import *
  82. +
  83. +class CallFunctionNode(Node, ArmLogicTreeNode):
  84. + '''Call Haxe function node'''
  85. + bl_idname = 'LNCallFunctionNode'
  86. + bl_label = 'Call Function'
  87. + bl_icon = 'GAME'
  88. + min_inputs = 3
  89. +
  90. + def __init__(self):
  91. + array_nodes[str(id(self))] = self
  92. +
  93. + def init(self, context):
  94. + self.inputs.new('ArmNodeSocketAction', 'In')
  95. + self.inputs.new('NodeSocketShader', 'Trait/Any')
  96. + self.inputs.new('NodeSocketString', 'Function')
  97. + self.outputs.new('ArmNodeSocketAction', 'Out')
  98. + self.outputs.new('NodeSocketShader', 'Result')
  99. +
  100. + def draw_buttons(self, context, layout):
  101. + row = layout.row(align=True)
  102. + op = row.operator('arm.node_add_input', text='Add Arg', icon='PLUS', emboss=True)
  103. + op.node_index = str(id(self))
  104. + op.socket_type = 'NodeSocketShader'
  105. + op.name_format = "Arg {0}"
  106. + op.index_name_offset = -2
  107. + op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
  108. + op2.node_index = str(id(self))
  109. +
  110. +add_node(CallFunctionNode, category='Action')
  111. diff --git a/blender/arm/logicnode/arm_nodes.py b/blender/arm/logicnode/arm_nodes.py
  112. index db257d68..eb43cc24 100644
  113. --- a/blender/arm/logicnode/arm_nodes.py
  114. +++ b/blender/arm/logicnode/arm_nodes.py
  115. @@ -122,11 +122,13 @@ class ArmNodeAddInputButton(bpy.types.Operator):
  116. bl_label = 'Add Input'
  117. node_index = StringProperty(name='Node Index', default='')
  118. socket_type = StringProperty(name='Socket Type', default='NodeSocketShader')
  119. + name_format = StringProperty(name='Name Format', default='Input {0}')
  120. + index_name_offset = IntProperty(name='Index Name Offset', default=0)
  121.  
  122. def execute(self, context):
  123. global array_nodes
  124. inps = array_nodes[self.node_index].inputs
  125. - inps.new(self.socket_type, 'Input ' + str(len(inps)))
  126. + inps.new(self.socket_type, self.name_format.format(str(len(inps) + self.index_name_offset)))
  127. return{'FINISHED'}
  128.  
  129. class ArmNodeAddInputValueButton(bpy.types.Operator):
  130. @@ -178,11 +180,13 @@ class ArmNodeAddOutputButton(bpy.types.Operator):
  131. bl_label = 'Add Output'
  132. node_index = StringProperty(name='Node Index', default='')
  133. socket_type = StringProperty(name='Socket Type', default='NodeSocketShader')
  134. + name_format = StringProperty(name='Name Format', default='Output {0}')
  135. + index_name_offset = IntProperty(name='Index Name Offset', default=0)
  136.  
  137. def execute(self, context):
  138. global array_nodes
  139. outs = array_nodes[self.node_index].outputs
  140. - outs.new(self.socket_type, 'Output ' + str(len(outs)))
  141. + outs.new(self.socket_type, self.name_format.format(str(len(outs) + self.index_name_offset)))
  142. return{'FINISHED'}
  143.  
  144. class ArmNodeRemoveOutputButton(bpy.types.Operator):
  145. diff --git a/blender/arm/logicnode/logic_function.py b/blender/arm/logicnode/logic_function.py
  146. new file mode 100644
  147. index 00000000..6e5cb9ea
  148. --- /dev/null
  149. +++ b/blender/arm/logicnode/logic_function.py
  150. @@ -0,0 +1,33 @@
  151. +import bpy
  152. +from bpy.props import *
  153. +from bpy.types import Node, NodeSocket
  154. +from arm.logicnode.arm_nodes import *
  155. +
  156. +class FunctionNode(Node, ArmLogicTreeNode):
  157. + '''Function node'''
  158. + bl_idname = 'LNFunctionNode'
  159. + bl_label = 'Function'
  160. + bl_icon = 'CURVE_PATH'
  161. + min_outputs = 1
  162. +
  163. + def __init__(self):
  164. + array_nodes[str(id(self))] = self
  165. +
  166. + def init(self, context):
  167. + self.outputs.new('ArmNodeSocketAction', 'Out')
  168. +
  169. + function_name = StringProperty(name="Name")
  170. +
  171. + def draw_buttons(self, context, layout):
  172. + row = layout.row(align=True)
  173. + row.prop(self, 'function_name')
  174. + row = layout.row(align=True)
  175. + op = row.operator('arm.node_add_output', text='Add Arg', icon='PLUS', emboss=True)
  176. + op.node_index = str(id(self))
  177. + op.socket_type = 'NodeSocketShader'
  178. + op.name_format = "Arg {0}"
  179. + op.index_name_offset = 0
  180. + op2 = row.operator('arm.node_remove_output', text='', icon='X', emboss=True)
  181. + op2.node_index = str(id(self))
  182. +
  183. +add_node(FunctionNode, category='Logic')
  184. diff --git a/blender/arm/logicnode/logic_function_output.py b/blender/arm/logicnode/logic_function_output.py
  185. new file mode 100644
  186. index 00000000..dfc5fd90
  187. --- /dev/null
  188. +++ b/blender/arm/logicnode/logic_function_output.py
  189. @@ -0,0 +1,22 @@
  190. +import bpy
  191. +from bpy.props import *
  192. +from bpy.types import Node, NodeSocket
  193. +from arm.logicnode.arm_nodes import *
  194. +
  195. +class FunctionOutputNode(Node, ArmLogicTreeNode):
  196. + '''Function output node'''
  197. + bl_idname = 'LNFunctionOutputNode'
  198. + bl_label = 'Function Output'
  199. + bl_icon = 'CURVE_PATH'
  200. +
  201. + def init(self, context):
  202. + self.inputs.new('ArmNodeSocketAction', 'In')
  203. + self.inputs.new('NodeSocketShader', 'Value')
  204. +
  205. + function_name = StringProperty(name="Name")
  206. +
  207. + def draw_buttons(self, context, layout):
  208. + row = layout.row(align=True)
  209. + row.prop(self, 'function_name')
  210. +
  211. +add_node(FunctionOutputNode, category='Logic')
  212. diff --git a/blender/arm/make_logic.py b/blender/arm/make_logic.py
  213. index 833cba1b..72beb9b4 100755
  214. --- a/blender/arm/make_logic.py
  215. +++ b/blender/arm/make_logic.py
  216. @@ -6,6 +6,8 @@ from arm.exporter import ArmoryExporter
  217.  
  218. parsed_nodes = []
  219. parsed_ids = dict() # Sharing node data
  220. +function_nodes = dict()
  221. +function_node_outputs = dict()
  222. group_name = ''
  223.  
  224. def get_logic_trees():
  225. @@ -32,9 +34,13 @@ def build():
  226. def build_node_tree(node_group):
  227. global parsed_nodes
  228. global parsed_ids
  229. + global function_nodes
  230. + global function_node_outputs
  231. global group_name
  232. parsed_nodes = []
  233. parsed_ids = dict()
  234. + function_nodes = dict()
  235. + function_node_outputs = dict()
  236. root_nodes = get_root_nodes(node_group)
  237.  
  238. pack_path = arm.utils.safestr(bpy.data.worlds['Arm'].arm_project_package)
  239. @@ -54,15 +60,39 @@ def build_node_tree(node_group):
  240. with open(file, 'w') as f:
  241. f.write('package ' + pack_path + '.node;\n\n')
  242. f.write('@:keep class ' + group_name + ' extends armory.logicnode.LogicTree {\n\n')
  243. - f.write('\tpublic function new() { super();')
  244. + f.write('\tvar functionNodes:Map<String, armory.logicnode.FunctionNode>;\n\n')
  245. + f.write('\tvar functionOutputNodes:Map<String, armory.logicnode.FunctionOutputNode>;\n\n')
  246. + f.write('\tpublic function new() {\n')
  247. + f.write('\t\tsuper();\n')
  248. if bpy.data.worlds['Arm'].arm_play_console:
  249. - f.write(' name = "' + group_name + '";')
  250. - f.write(' notifyOnAdd(add); }\n\n')
  251. + f.write('\t\tname = "' + group_name + '";\n')
  252. + f.write('\t\tthis.functionNodes = new Map();\n')
  253. + f.write('\t\tthis.functionOutputNodes = new Map();\n')
  254. + f.write('\t\tnotifyOnAdd(add);\n')
  255. + f.write('\t}\n\n')
  256. f.write('\toverride public function add() {\n')
  257. for node in root_nodes:
  258. build_node(node, f)
  259. f.write('\t}\n')
  260. - f.write('}\n')
  261. +
  262. + # Create node functions
  263. + for node_name in function_nodes:
  264. + node = function_nodes[node_name]
  265. + function_name = node.function_name
  266. + f.write('\n\tpublic function ' + function_name + '(')
  267. + for i in range(0, len(node.outputs) - 1):
  268. + if i != 0: f.write(', ')
  269. + f.write('arg' + str(i) + ':Dynamic')
  270. + f.write(') {\n')
  271. + f.write('\t\tvar functionNode = this.functionNodes["' + node_name + '"];\n')
  272. + f.write('\t\tfunctionNode.args = [];\n')
  273. + for i in range(0, len(node.outputs) - 1):
  274. + f.write('\t\tfunctionNode.args.push(arg' + str(i) + ');\n')
  275. + f.write('\t\tfunctionNode.run(0);\n')
  276. + if function_node_outputs.get(function_name) != None:
  277. + f.write('\t\treturn this.functionOutputNodes["' + function_node_outputs[function_name] + '"].result;\n')
  278. + f.write('\t}\n\n')
  279. + f.write('}')
  280. node_group.is_cached = True
  281.  
  282. def build_node(node, f):
  283. @@ -94,6 +124,15 @@ def build_node(node, f):
  284. node_type = node.bl_idname[2:] # Discard 'LN'TimeNode prefix
  285. f.write('\t\tvar ' + name + ' = new armory.logicnode.' + node_type + '(this);\n')
  286.  
  287. + # Handle Function Nodes
  288. + if node_type == 'FunctionNode':
  289. + f.write('\t\tthis.functionNodes.set("' + name + '", ' + name + ');\n')
  290. + function_nodes[name] = node
  291. + elif node_type == 'FunctionOutputNode':
  292. + f.write('\t\tthis.functionOutputNodes.set("' + name + '", ' + name + ');\n')
  293. + # Index function output name by corresponding function name
  294. + function_node_outputs[node.function_name] = name
  295. +
  296. # Watch in debug console
  297. if node.arm_watch and bpy.data.worlds['Arm'].arm_play_console:
  298. f.write('\t\t' + name + '.name = "' + name[1:] + '";\n')
Add Comment
Please, Sign In to add comment