Fix LN live patch when using multiple instances of the same logic tree
This commit is contained in:
parent
ee208ece18
commit
bce14549ac
|
@ -3,7 +3,10 @@ package armory.logicnode;
|
||||||
class LogicTree extends iron.Trait {
|
class LogicTree extends iron.Trait {
|
||||||
|
|
||||||
#if arm_patch
|
#if arm_patch
|
||||||
public static var nodeTrees = new Map<String, LogicTree>();
|
/**
|
||||||
|
Stores all trait instances of the tree via its name.
|
||||||
|
**/
|
||||||
|
public static var nodeTrees = new Map<String, Array<LogicTree>>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
[node name => logic node] for later node replacement for live patching.
|
[node name => logic node] for later node replacement for live patching.
|
||||||
|
|
|
@ -33,147 +33,161 @@ class LivePatch extends iron.Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchCreateNodeLink(treeName: String, fromNodeName: String, toNodeName: String, fromIndex: Int, toIndex: Int) {
|
public static function patchCreateNodeLink(treeName: String, fromNodeName: String, toNodeName: String, fromIndex: Int, toIndex: Int) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var fromNode = tree.nodes[fromNodeName];
|
for (tree in trees) {
|
||||||
var toNode = tree.nodes[toNodeName];
|
var fromNode = tree.nodes[fromNodeName];
|
||||||
if (fromNode == null || toNode == null) return;
|
var toNode = tree.nodes[toNodeName];
|
||||||
|
if (fromNode == null || toNode == null) return;
|
||||||
|
|
||||||
LogicNode.addLink(fromNode, toNode, fromIndex, toIndex);
|
LogicNode.addLink(fromNode, toNode, fromIndex, toIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchSetNodeLinks(treeName: String, nodeName: String, inputDatas: Array<Dynamic>, outputDatas: Array<Array<Dynamic>>) {
|
public static function patchSetNodeLinks(treeName: String, nodeName: String, inputDatas: Array<Dynamic>, outputDatas: Array<Array<Dynamic>>) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var node = tree.nodes[nodeName];
|
for (tree in trees) {
|
||||||
if (node == null) return;
|
var node = tree.nodes[nodeName];
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
node.clearInputs();
|
node.clearInputs();
|
||||||
node.clearOutputs();
|
node.clearOutputs();
|
||||||
|
|
||||||
for (inputData in inputDatas) {
|
for (inputData in inputDatas) {
|
||||||
var fromNode: LogicNode;
|
var fromNode: LogicNode;
|
||||||
var fromIndex: Int;
|
var fromIndex: Int;
|
||||||
|
|
||||||
if (inputData.isLinked) {
|
if (inputData.isLinked) {
|
||||||
fromNode = tree.nodes[inputData.fromNode];
|
fromNode = tree.nodes[inputData.fromNode];
|
||||||
if (fromNode == null) continue;
|
if (fromNode == null) continue;
|
||||||
fromIndex = inputData.fromIndex;
|
fromIndex = inputData.fromIndex;
|
||||||
}
|
|
||||||
else {
|
|
||||||
fromNode = LogicNode.createSocketDefaultNode(node.tree, inputData.socketType, inputData.socketValue);
|
|
||||||
fromIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogicNode.addLink(fromNode, node, fromIndex, inputData.toIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (outputData in outputDatas) {
|
|
||||||
for (linkData in outputData) {
|
|
||||||
var toNode: LogicNode;
|
|
||||||
var toIndex: Int;
|
|
||||||
|
|
||||||
if (linkData.isLinked) {
|
|
||||||
toNode = tree.nodes[linkData.toNode];
|
|
||||||
if (toNode == null) continue;
|
|
||||||
toIndex = linkData.toIndex;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
toNode = LogicNode.createSocketDefaultNode(node.tree, linkData.socketType, linkData.socketValue);
|
fromNode = LogicNode.createSocketDefaultNode(node.tree, inputData.socketType, inputData.socketValue);
|
||||||
toIndex = 0;
|
fromIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogicNode.addLink(node, toNode, linkData.fromIndex, toIndex);
|
LogicNode.addLink(fromNode, node, fromIndex, inputData.toIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (outputData in outputDatas) {
|
||||||
|
for (linkData in outputData) {
|
||||||
|
var toNode: LogicNode;
|
||||||
|
var toIndex: Int;
|
||||||
|
|
||||||
|
if (linkData.isLinked) {
|
||||||
|
toNode = tree.nodes[linkData.toNode];
|
||||||
|
if (toNode == null) continue;
|
||||||
|
toIndex = linkData.toIndex;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toNode = LogicNode.createSocketDefaultNode(node.tree, linkData.socketType, linkData.socketValue);
|
||||||
|
toIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogicNode.addLink(node, toNode, linkData.fromIndex, toIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchUpdateNodeProp(treeName: String, nodeName: String, propName: String, value: Dynamic) {
|
public static function patchUpdateNodeProp(treeName: String, nodeName: String, propName: String, value: Dynamic) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var node = tree.nodes[nodeName];
|
for (tree in trees) {
|
||||||
if (node == null) return;
|
var node = tree.nodes[nodeName];
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
Reflect.setField(node, propName, value);
|
Reflect.setField(node, propName, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchUpdateNodeInputVal(treeName: String, nodeName: String, socketIndex: Int, value: Dynamic) {
|
public static function patchUpdateNodeInputVal(treeName: String, nodeName: String, socketIndex: Int, value: Dynamic) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var node = tree.nodes[nodeName];
|
for (tree in trees) {
|
||||||
if (node == null) return;
|
var node = tree.nodes[nodeName];
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
node.inputs[socketIndex].set(value);
|
node.inputs[socketIndex].set(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchNodeDelete(treeName: String, nodeName: String) {
|
public static function patchNodeDelete(treeName: String, nodeName: String) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var node = tree.nodes[nodeName];
|
for (tree in trees) {
|
||||||
if (node == null) return;
|
var node = tree.nodes[nodeName];
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
node.clearOutputs();
|
node.clearOutputs();
|
||||||
node.clearInputs();
|
node.clearInputs();
|
||||||
tree.nodes.remove(nodeName);
|
tree.nodes.remove(nodeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchNodeCreate(treeName: String, nodeName: String, nodeType: String, propDatas: Array<Array<Dynamic>>, inputDatas: Array<Array<Dynamic>>, outputDatas: Array<Array<Dynamic>>) {
|
public static function patchNodeCreate(treeName: String, nodeName: String, nodeType: String, propDatas: Array<Array<Dynamic>>, inputDatas: Array<Array<Dynamic>>, outputDatas: Array<Array<Dynamic>>) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
// No further constructor parameters required here, all variable nodes
|
for (tree in trees) {
|
||||||
// use optional further parameters and all values are set later in this
|
// No further constructor parameters required here, all variable nodes
|
||||||
// function.
|
// use optional further parameters and all values are set later in this
|
||||||
var newNode: LogicNode = Type.createInstance(Type.resolveClass(nodeType), [tree]);
|
// function.
|
||||||
newNode.name = nodeName;
|
var newNode: LogicNode = Type.createInstance(Type.resolveClass(nodeType), [tree]);
|
||||||
tree.nodes[nodeName] = newNode;
|
newNode.name = nodeName;
|
||||||
|
tree.nodes[nodeName] = newNode;
|
||||||
|
|
||||||
for (propData in propDatas) {
|
for (propData in propDatas) {
|
||||||
Reflect.setField(newNode, propData[0], propData[1]);
|
Reflect.setField(newNode, propData[0], propData[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (inputData in inputDatas) {
|
for (inputData in inputDatas) {
|
||||||
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (outputData in outputDatas) {
|
for (outputData in outputDatas) {
|
||||||
LogicNode.addLink(newNode, LogicNode.createSocketDefaultNode(newNode.tree, outputData[0], outputData[1]), i++, 0);
|
LogicNode.addLink(newNode, LogicNode.createSocketDefaultNode(newNode.tree, outputData[0], outputData[1]), i++, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function patchNodeCopy(treeName: String, nodeName: String, newNodeName: String, copyProps: Array<String>, inputDatas: Array<Array<Dynamic>>, outputDatas: Array<Array<Dynamic>>) {
|
public static function patchNodeCopy(treeName: String, nodeName: String, newNodeName: String, copyProps: Array<String>, inputDatas: Array<Array<Dynamic>>, outputDatas: Array<Array<Dynamic>>) {
|
||||||
var tree = LogicTree.nodeTrees[treeName];
|
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||||
if (tree == null) return;
|
var trees = LogicTree.nodeTrees[treeName];
|
||||||
|
|
||||||
var node = tree.nodes[nodeName];
|
for (tree in trees) {
|
||||||
if (node == null) return;
|
var node = tree.nodes[nodeName];
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
// No further constructor parameters required here, all variable nodes
|
// No further constructor parameters required here, all variable nodes
|
||||||
// use optional further parameters and all values are set later in this
|
// use optional further parameters and all values are set later in this
|
||||||
// function.
|
// function.
|
||||||
var newNode: LogicNode = Type.createInstance(Type.getClass(node), [tree]);
|
var newNode: LogicNode = Type.createInstance(Type.getClass(node), [tree]);
|
||||||
newNode.name = newNodeName;
|
newNode.name = newNodeName;
|
||||||
tree.nodes[newNodeName] = newNode;
|
tree.nodes[newNodeName] = newNode;
|
||||||
|
|
||||||
for (propName in copyProps) {
|
for (propName in copyProps) {
|
||||||
Reflect.setField(newNode, propName, Reflect.field(node, propName));
|
Reflect.setField(newNode, propName, Reflect.field(node, propName));
|
||||||
}
|
}
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (inputData in inputDatas) {
|
for (inputData in inputDatas) {
|
||||||
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (outputData in outputDatas) {
|
for (outputData in outputDatas) {
|
||||||
LogicNode.addLink(newNode, LogicNode.createSocketDefaultNode(newNode.tree, outputData[0], outputData[1]), i++, 0);
|
LogicNode.addLink(newNode, LogicNode.createSocketDefaultNode(newNode.tree, outputData[0], outputData[1]), i++, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,14 @@ def build_node_tree(node_group: 'arm.nodes_logic.ArmLogicTree'):
|
||||||
f.write('\t\tthis.functionNodes = new Map();\n')
|
f.write('\t\tthis.functionNodes = new Map();\n')
|
||||||
f.write('\t\tthis.functionOutputNodes = new Map();\n')
|
f.write('\t\tthis.functionOutputNodes = new Map();\n')
|
||||||
if arm.utils.is_livepatch_enabled():
|
if arm.utils.is_livepatch_enabled():
|
||||||
f.write(f'\t\tarmory.logicnode.LogicTree.nodeTrees["{group_name}"] = this;\n')
|
# Store a reference to this trait instance in Logictree.nodeTrees
|
||||||
|
f.write('\t\tvar nodeTrees = armory.logicnode.LogicTree.nodeTrees;\n')
|
||||||
|
f.write(f'\t\tif (nodeTrees.exists("{group_name}")) ' + '{\n')
|
||||||
|
f.write(f'\t\t\tnodeTrees["{group_name}"].push(this);\n')
|
||||||
|
f.write('\t\t} else {\n')
|
||||||
|
f.write(f'\t\t\tnodeTrees["{group_name}"] = cast [this];\n')
|
||||||
|
f.write('\t\t}\n')
|
||||||
|
f.write('\t\tnotifyOnRemove(() -> { nodeTrees.remove("' + group_name + '"); });\n')
|
||||||
f.write('\t\tnotifyOnAdd(add);\n')
|
f.write('\t\tnotifyOnAdd(add);\n')
|
||||||
f.write('\t}\n\n')
|
f.write('\t}\n\n')
|
||||||
f.write('\toverride public function add() {\n')
|
f.write('\toverride public function add() {\n')
|
||||||
|
@ -217,9 +224,9 @@ def build_node(node: bpy.types.Node, f: TextIO) -> Optional[str]:
|
||||||
f.write(f'\t\t{"var __link = " if use_live_patch else ""}armory.logicnode.LogicNode.addLink({inp_name}, {name}, {inp_from}, {idx});\n')
|
f.write(f'\t\t{"var __link = " if use_live_patch else ""}armory.logicnode.LogicNode.addLink({inp_name}, {name}, {inp_from}, {idx});\n')
|
||||||
if use_live_patch:
|
if use_live_patch:
|
||||||
to_type = inp.arm_socket_type
|
to_type = inp.arm_socket_type
|
||||||
f.write(f'\t\t__link.fromType = "{from_type}";')
|
f.write(f'\t\t__link.fromType = "{from_type}";\n')
|
||||||
f.write(f'\t\t__link.toType = "{to_type}";')
|
f.write(f'\t\t__link.toType = "{to_type}";\n')
|
||||||
f.write(f'\t\t__link.toValue = {arm.node_utils.haxe_format_socket_val(inp.get_default_value())};')
|
f.write(f'\t\t__link.toValue = {arm.node_utils.haxe_format_socket_val(inp.get_default_value())};\n')
|
||||||
|
|
||||||
# Create outputs
|
# Create outputs
|
||||||
for idx, out in enumerate(node.outputs):
|
for idx, out in enumerate(node.outputs):
|
||||||
|
@ -229,9 +236,9 @@ def build_node(node: bpy.types.Node, f: TextIO) -> Optional[str]:
|
||||||
f.write(f'\t\t{"var __link = " if use_live_patch else ""}armory.logicnode.LogicNode.addLink({name}, {build_default_node(out)}, {idx}, 0);\n')
|
f.write(f'\t\t{"var __link = " if use_live_patch else ""}armory.logicnode.LogicNode.addLink({name}, {build_default_node(out)}, {idx}, 0);\n')
|
||||||
if use_live_patch:
|
if use_live_patch:
|
||||||
out_type = out.arm_socket_type
|
out_type = out.arm_socket_type
|
||||||
f.write(f'\t\t__link.fromType = "{out_type}";')
|
f.write(f'\t\t__link.fromType = "{out_type}";\n')
|
||||||
f.write(f'\t\t__link.toType = "{out_type}";')
|
f.write(f'\t\t__link.toType = "{out_type}";\n')
|
||||||
f.write(f'\t\t__link.toValue = {arm.node_utils.haxe_format_socket_val(out.get_default_value())};')
|
f.write(f'\t\t__link.toValue = {arm.node_utils.haxe_format_socket_val(out.get_default_value())};\n')
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue