diff --git a/Sources/armory/trait/internal/LivePatch.hx b/Sources/armory/trait/internal/LivePatch.hx index d51c43a1..190a85ff 100644 --- a/Sources/armory/trait/internal/LivePatch.hx +++ b/Sources/armory/trait/internal/LivePatch.hx @@ -66,6 +66,45 @@ class LivePatch extends iron.Trait { @:privateAccess node.inputs[socketIndex].set(value); } + public static function patchNodeDelete(treeName: String, nodeName: String, outputDatas: Array>) { + var tree = LogicTree.nodeTrees[treeName]; + if (tree == null) return; + + var node = tree.nodes[nodeName]; + if (node == null) return; + + // Remove this node from the outputs of connected nodes + for (input in node.inputs) { + var inNodeOutputs = input.node.outputs; + + // Default nodes don't have outputs when exported from Blender + if (input.from < inNodeOutputs.length) { + for (outNode in inNodeOutputs[input.from]) { + if (outNode == node) { + inNodeOutputs[input.from].remove(outNode); + } + } + } + + } + + // Replace connected inputs of other nodes with default nodes + for (outputNodes in node.outputs) { + for (outNode in outputNodes) { + for (outNodeInput in outNode.inputs) { + if (outNodeInput.node == node) { + var outputIndex = outNodeInput.from; + var socketType = outputDatas[outputIndex][0]; + var socketValue = outputDatas[outputIndex][1]; + outNodeInput.node = createSocketDefaultNode(node.tree, socketType, socketValue); + } + } + } + } + + tree.nodes.remove(nodeName); + } + public static function patchNodeCopy(treeName: String, nodeName: String, newNodeName: String, copyProps: Array, inputDatas: Array>, outputDatas: Array>) { var tree = LogicTree.nodeTrees[treeName]; if (tree == null) return; diff --git a/blender/arm/live_patch.py b/blender/arm/live_patch.py index 0affd3f2..1130e5b5 100644 --- a/blender/arm/live_patch.py +++ b/blender/arm/live_patch.py @@ -215,6 +215,18 @@ def send_event(event_id: str, opt_data: Any = None): js = f'LivePatch.patchUpdateNodeInputVal("{tree_name}", "{node_name}", {socket_index}, {value});' write_patch(js) + elif event_id == 'ln_delete': + node: ArmLogicTreeNode = opt_data + + tree_name = arm.node_utils.get_export_tree_name(node.get_tree()) + node_name = arm.node_utils.get_export_node_name(node)[1:] + + out_data = [(out.arm_socket_type, out.get_default_value()) for out in node.outputs] + out_data = arm.node_utils.haxe_format_socket_val(out_data) + + js = f'LivePatch.patchNodeDelete("{tree_name}", "{node_name}", {out_data});' + write_patch(js) + elif event_id == 'ln_copy': newnode: ArmLogicTreeNode node: ArmLogicTreeNode diff --git a/blender/arm/logicnode/arm_nodes.py b/blender/arm/logicnode/arm_nodes.py index 6be13f4f..50db2c43 100644 --- a/blender/arm/logicnode/arm_nodes.py +++ b/blender/arm/logicnode/arm_nodes.py @@ -54,6 +54,10 @@ class ArmLogicTreeNode(bpy.types.Node): def get_tree(self): return self.id_data + def free(self): + """Called before the node is deleted.""" + arm.live_patch.send_event('ln_delete', self) + def copy(self, node): """Called if the node was copied. `self` holds the copied node, `node` the original one.