diff --git a/Sources/armory/logicnode/GamepadCoordsNode.hx b/Sources/armory/logicnode/GamepadCoordsNode.hx index d7c334bb..01394156 100644 --- a/Sources/armory/logicnode/GamepadCoordsNode.hx +++ b/Sources/armory/logicnode/GamepadCoordsNode.hx @@ -32,6 +32,10 @@ class GamepadCoordsNode extends LogicNode { coords.x = gamepad.rightStick.movementX; coords.y = gamepad.rightStick.movementY; return coords; + } else if(from == 4) { + return gamepad.down("l2"); + } else if(from == 5) { + return gamepad.down("r2"); } return null; } diff --git a/Sources/armory/logicnode/GamepadNode.hx b/Sources/armory/logicnode/GamepadNode.hx index 8a31a099..82cb99e7 100644 --- a/Sources/armory/logicnode/GamepadNode.hx +++ b/Sources/armory/logicnode/GamepadNode.hx @@ -7,6 +7,28 @@ class GamepadNode extends LogicNode { public function new(tree:LogicTree) { super(tree); + + tree.notifyOnUpdate(update); + } + + function update() { + var num:Int = inputs[0].get(); + var gamepad = iron.system.Input.getGamepad(num); + if (gamepad == null) return; + var b = false; + switch (property0) { + case "Down": + b = gamepad.down(property1) > 0.0; + case "Started": + b = gamepad.started(property1); + case "Released": + b = gamepad.released(property1); + // case "Moved Left": + // b = gamepad.leftStick.movementX != 0 || gamepad.leftStick.movementY != 0; + // case "Moved Right": + // b = gamepad.rightStick.movementX != 0 || gamepad.rightStick.movementY != 0; + } + if (b) runOutput(0); } override function get(from:Int):Dynamic { @@ -14,11 +36,11 @@ class GamepadNode extends LogicNode { var gamepad = iron.system.Input.getGamepad(num); switch (property0) { case "Down": - return gamepad.down(property1); + return gamepad.down(property1) > 0.0; case "Started": - return gamepad.started(property1) ? 1.0 : 0.0; + return gamepad.started(property1); case "Released": - return gamepad.released(property1) ? 1.0 : 0.0; + return gamepad.released(property1); // case "Moved Left": // return (gamepad.leftStick.movementX != 0 || gamepad.leftStick.movementY != 0) ? 1.0 : 0.0; // case "Moved Right": diff --git a/Sources/armory/logicnode/KeyboardNode.hx b/Sources/armory/logicnode/KeyboardNode.hx index a25f3616..f3ed8a9f 100644 --- a/Sources/armory/logicnode/KeyboardNode.hx +++ b/Sources/armory/logicnode/KeyboardNode.hx @@ -7,8 +7,24 @@ class KeyboardNode extends LogicNode { public function new(tree:LogicTree) { super(tree); + + tree.notifyOnUpdate(update); } - + + function update() { + var keyboard = iron.system.Input.getKeyboard(); + var b = false; + switch (property0) { + case "Down": + b = keyboard.down(property1); + case "Started": + b = keyboard.started(property1); + case "Released": + b = keyboard.released(property1); + } + if (b) runOutput(0); + } + override function get(from:Int):Dynamic { var keyboard = iron.system.Input.getKeyboard(); switch (property0) { diff --git a/Sources/armory/logicnode/MouseNode.hx b/Sources/armory/logicnode/MouseNode.hx index ee49fb35..4f1d0be1 100644 --- a/Sources/armory/logicnode/MouseNode.hx +++ b/Sources/armory/logicnode/MouseNode.hx @@ -7,8 +7,26 @@ class MouseNode extends LogicNode { public function new(tree:LogicTree) { super(tree); + + tree.notifyOnUpdate(update); } - + + function update() { + var mouse = iron.system.Input.getMouse(); + var b = false; + switch (property0) { + case "Down": + b = mouse.down(property1); + case "Started": + b = mouse.started(property1); + case "Released": + b = mouse.released(property1); + case "Moved": + b = mouse.moved; + } + if (b) runOutput(0); + } + override function get(from:Int):Dynamic { var mouse = iron.system.Input.getMouse(); switch (property0) { diff --git a/Sources/armory/logicnode/SurfaceNode.hx b/Sources/armory/logicnode/SurfaceNode.hx index d1d09fb0..c31e12c8 100644 --- a/Sources/armory/logicnode/SurfaceNode.hx +++ b/Sources/armory/logicnode/SurfaceNode.hx @@ -6,19 +6,37 @@ class SurfaceNode extends LogicNode { public function new(tree:LogicTree) { super(tree); + + tree.notifyOnUpdate(update); + } + + function update() { + var surface = iron.system.Input.getSurface(); + var b = false; + switch (property0) { + case "Touched": + b = surface.down(); + case "Started": + b = surface.started(); + case "Released": + b = surface.released(); + case "Moved": + b = surface.moved(); + } + if (b) runOutput(0); } override function get(from:Int):Dynamic { var surface = iron.system.Input.getSurface(); switch (property0) { case "Touched": - return surface.down; + return surface.down(); case "Started": - return surface.started; + return surface.started(); case "Released": - return surface.released; + return surface.released(); case "Moved": - return surface.moved; + return surface.moved(); } return false; } diff --git a/Sources/armory/logicnode/VirtualButtonNode.hx b/Sources/armory/logicnode/VirtualButtonNode.hx index 0f130bf7..b5e3babb 100644 --- a/Sources/armory/logicnode/VirtualButtonNode.hx +++ b/Sources/armory/logicnode/VirtualButtonNode.hx @@ -7,6 +7,23 @@ class VirtualButtonNode extends LogicNode { public function new(tree:LogicTree) { super(tree); + + tree.notifyOnUpdate(update); + } + + function update() { + var vb = iron.system.Input.getVirtualButton(property1); + if (vb == null) return; + var b = false; + switch (property0) { + case "Down": + b = vb.down; + case "Started": + b = vb.started; + case "Released": + b = vb.released; + } + if (b) runOutput(0); } override function get(from:Int):Dynamic { diff --git a/blender/arm/logicnode/input_gamepad.py b/blender/arm/logicnode/input_gamepad.py index b8144a03..88b122cc 100644 --- a/blender/arm/logicnode/input_gamepad.py +++ b/blender/arm/logicnode/input_gamepad.py @@ -6,7 +6,7 @@ from arm.logicnode.arm_nodes import * class GamepadNode(Node, ArmLogicTreeNode): '''Gamepad node''' bl_idname = 'LNGamepadNode' - bl_label = 'Gamepad State' + bl_label = 'Gamepad' bl_icon = 'CURVE_PATH' property0: EnumProperty( @@ -22,10 +22,10 @@ class GamepadNode(Node, ArmLogicTreeNode): ('circle', 'circle / b', 'circle / b'), ('square', 'square / x', 'square / x'), ('triangle', 'triangle / y', 'triangle / y'), - ('l1', 'l1', 'l1'), - ('r1', 'r1', 'r1'), - ('l2', 'l2', 'l2'), - ('r2', 'r2', 'r2'), + ('l1', 'l1 / lb', 'l1 / lb'), + ('r1', 'r1 / rb', 'r1 / rb'), + ('l2', 'l2 / lt', 'l2 / lt'), + ('r2', 'r2 / rt', 'r2 / rt'), ('share', 'share', 'share'), ('options', 'options', 'options'), ('l3', 'l3', 'l3'), @@ -39,7 +39,8 @@ class GamepadNode(Node, ArmLogicTreeNode): name='', default='cross') def init(self, context): - self.outputs.new('NodeSocketFloat', 'Value') + self.outputs.new('ArmNodeSocketAction', 'Out') + self.outputs.new('NodeSocketBool', 'State') self.inputs.new('NodeSocketInt', 'Gamepad') def draw_buttons(self, context, layout): diff --git a/blender/arm/logicnode/input_gamepad_coords.py b/blender/arm/logicnode/input_gamepad_coords.py index 8acdb5d8..23c38cb7 100644 --- a/blender/arm/logicnode/input_gamepad_coords.py +++ b/blender/arm/logicnode/input_gamepad_coords.py @@ -14,6 +14,8 @@ class GamepadCoordsNode(Node, ArmLogicTreeNode): self.outputs.new('NodeSocketVector', 'Right Stick') self.outputs.new('NodeSocketVector', 'Left Movement') self.outputs.new('NodeSocketVector', 'Right Movement') + self.outputs.new('NodeSocketFloat', 'Left Trigger') + self.outputs.new('NodeSocketFloat', 'Right Trigger') self.inputs.new('NodeSocketInt', 'Gamepad') add_node(GamepadCoordsNode, category='Input') diff --git a/blender/arm/logicnode/input_keyboard.py b/blender/arm/logicnode/input_keyboard.py index 38acf39a..8903f570 100644 --- a/blender/arm/logicnode/input_keyboard.py +++ b/blender/arm/logicnode/input_keyboard.py @@ -6,7 +6,7 @@ from arm.logicnode.arm_nodes import * class KeyboardNode(Node, ArmLogicTreeNode): '''Keyboard node''' bl_idname = 'LNKeyboardNode' - bl_label = 'Keyboard State' + bl_label = 'Keyboard' bl_icon = 'CURVE_PATH' property0: EnumProperty( @@ -71,6 +71,7 @@ class KeyboardNode(Node, ArmLogicTreeNode): name='', default='space') def init(self, context): + self.outputs.new('ArmNodeSocketAction', 'Out') self.outputs.new('NodeSocketBool', 'State') def draw_buttons(self, context, layout): diff --git a/blender/arm/logicnode/input_mouse.py b/blender/arm/logicnode/input_mouse.py index 783e2165..2f3fa965 100644 --- a/blender/arm/logicnode/input_mouse.py +++ b/blender/arm/logicnode/input_mouse.py @@ -6,7 +6,7 @@ from arm.logicnode.arm_nodes import * class MouseNode(Node, ArmLogicTreeNode): '''Mouse node''' bl_idname = 'LNMouseNode' - bl_label = 'Mouse State' + bl_label = 'Mouse' bl_icon = 'CURVE_PATH' property0: EnumProperty( items = [('Down', 'Down', 'Down'), @@ -21,6 +21,7 @@ class MouseNode(Node, ArmLogicTreeNode): name='', default='left') def init(self, context): + self.outputs.new('ArmNodeSocketAction', 'Out') self.outputs.new('NodeSocketBool', 'State') def draw_buttons(self, context, layout): diff --git a/blender/arm/logicnode/input_surface.py b/blender/arm/logicnode/input_surface.py index dc8c30ba..294e6702 100644 --- a/blender/arm/logicnode/input_surface.py +++ b/blender/arm/logicnode/input_surface.py @@ -6,7 +6,7 @@ from arm.logicnode.arm_nodes import * class SurfaceNode(Node, ArmLogicTreeNode): '''Surface node''' bl_idname = 'LNSurfaceNode' - bl_label = 'Surface State' + bl_label = 'Surface' bl_icon = 'CURVE_PATH' property0: EnumProperty( items = [('Touched', 'Touched', 'Touched'), @@ -16,6 +16,7 @@ class SurfaceNode(Node, ArmLogicTreeNode): name='', default='Touched') def init(self, context): + self.outputs.new('ArmNodeSocketAction', 'Out') self.outputs.new('NodeSocketBool', 'State') def draw_buttons(self, context, layout): diff --git a/blender/arm/logicnode/input_virtual_button.py b/blender/arm/logicnode/input_virtual_button.py index 3e00fd4e..d7ca1276 100644 --- a/blender/arm/logicnode/input_virtual_button.py +++ b/blender/arm/logicnode/input_virtual_button.py @@ -16,6 +16,7 @@ class VirtualButtonNode(Node, ArmLogicTreeNode): property1: StringProperty(name='', default='button') def init(self, context): + self.outputs.new('ArmNodeSocketAction', 'Out') self.outputs.new('NodeSocketBool', 'State') def draw_buttons(self, context, layout): diff --git a/blender/arm/nodes_logic.py b/blender/arm/nodes_logic.py index 8ea8ea8d..bbbebf7f 100755 --- a/blender/arm/nodes_logic.py +++ b/blender/arm/nodes_logic.py @@ -105,10 +105,88 @@ def draw_menu(self, context): layout.operator("arm.node_search", text="Search", icon="VIEWZOOM") layout.separator() +# node replacement code +replacements = {} + +def add_replacement(item): + replacements[item.from_node] = item + +def get_replaced_nodes(): + return replacements.keys() + +def get_replacement_for_node(node): + return replacements[node.bl_idname] + +class Replacement: + # represents a single replacement rule, this can replace exactly one node with another + # + # from_node: the node type to be removed + # to_node: the node type which takes from_node's place + # *SocketMapping: a map which defines how the sockets of the old node shall be connected to the new node + # {1: 2} means that anything connected to the socket with index 1 on the original node will be connected to the socket with index 2 on the new node + def __init__(self, from_node, to_node, in_socket_mapping, out_socket_mapping): + self.from_node = from_node + self.to_node = to_node + self.in_socket_mapping = in_socket_mapping + self.out_socket_mapping = out_socket_mapping + +# actual replacement code +def replace(tree, node): + replacement = get_replacement_for_node(node) + newnode = tree.nodes.new(replacement.to_node) + newnode.location = node.location + newnode.parent = node.parent + + parent = node.parent + while parent is not None: + newnode.location[0] += parent.location[0] + newnode.location[1] += parent.location[1] + parent = parent.parent + + for link in tree.links: + if link.from_node == node: + # this is an output link + for i in range(0, len(node.outputs)): + # check the outputs + # i represents the socket index + # do we want to remap it & is it the one referenced in the current link + if i in replacement.out_socket_mapping.keys() and node.outputs[i] == link.from_socket: + tree.links.new(newnode.outputs[replacement.out_socket_mapping.get(i)], link.to_socket) + + if link.to_node == node: + # this is an input link + for i in range(0, len(node.inputs)): + # check the inputs + # i represents the socket index + # do we want to remap it & is it the one referenced socket in the current link + if i in replacement.in_socket_mapping.keys() and node.inputs[i] == link.to_socket: + tree.links.new(newnode.inputs[replacement.in_socket_mapping.get(i)], link.from_socket) + tree.nodes.remove(node) + + +class ReplaceNodesOperator(bpy.types.Operator): + '''Automatically replaces deprecated nodes.''' + bl_idname = "node.replace" + bl_label = "Replace Nodes" + + def execute(self, context): + for tree in bpy.data.node_groups: + if tree.bl_idname == "ArmLogicTreeType": + for node in tree.nodes: + if node.bl_idname in get_replaced_nodes(): + print("Replacing "+ node.bl_idname+ " in Tree "+tree.name) + replace(tree, node) + return {'FINISHED'} + + @classmethod + def poll(cls, context): + return context.space_data != None and context.space_data.type == 'NODE_EDITOR' + def register(): bpy.utils.register_class(ArmLogicTree) bpy.utils.register_class(ARM_PT_LogicNodePanel) bpy.utils.register_class(ArmOpenNodeSource) + bpy.utils.register_class(ReplaceNodesOperator) register_nodes() bpy.utils.register_class(ArmNodeSearch) bpy.types.NODE_MT_add.prepend(draw_menu) @@ -116,6 +194,7 @@ def register(): def unregister(): bpy.types.NODE_MT_add.remove(draw_menu) bpy.utils.unregister_class(ArmNodeSearch) + bpy.utils.unregister_class(ReplaceNodesOperator) unregister_nodes() bpy.utils.unregister_class(ArmLogicTree) bpy.utils.unregister_class(ARM_PT_LogicNodePanel)