Merge pull request #2283 from MoritzBrueckner/live-patch
Live patch: refactor and logic nodes support
This commit is contained in:
commit
ce75516c59
|
@ -1,13 +1,11 @@
|
|||
package armory.logicnode;
|
||||
|
||||
import armory.trait.physics.PhysicsConstraint;
|
||||
#if arm_physics
|
||||
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintType;
|
||||
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintAxis;
|
||||
#end
|
||||
import iron.object.Object;
|
||||
import armory.trait.physics.RigidBody;
|
||||
import armory.logicnode.PhysicsConstraintNode;
|
||||
|
||||
#if arm_physics
|
||||
import armory.trait.physics.PhysicsConstraint;
|
||||
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintType;
|
||||
#end
|
||||
|
||||
class AddPhysicsConstraintNode extends LogicNode {
|
||||
|
||||
|
@ -21,115 +19,96 @@ class AddPhysicsConstraintNode extends LogicNode {
|
|||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var pivotObject:Object = inputs[1].get();
|
||||
var pivotObject: Object = inputs[1].get();
|
||||
rb1 = inputs[2].get();
|
||||
rb2 = inputs[3].get();
|
||||
var disableCollisions: Bool = inputs[4].get();
|
||||
var breakable: Bool = inputs[5].get();
|
||||
var breakingThreshold: Float = inputs[6].get();
|
||||
var type: ConstraintType = 0;
|
||||
|
||||
if (pivotObject == null || rb1 == null || rb2 == null) return;
|
||||
|
||||
#if arm_physics
|
||||
|
||||
var disableCollisions: Bool = inputs[4].get();
|
||||
var breakable: Bool = inputs[5].get();
|
||||
var breakingThreshold: Float = inputs[6].get();
|
||||
var type: ConstraintType = 0;
|
||||
|
||||
var con: PhysicsConstraint = pivotObject.getTrait(PhysicsConstraint);
|
||||
if(con == null)
|
||||
{
|
||||
switch(property0)
|
||||
{
|
||||
case 'Fixed':
|
||||
type = Fixed;
|
||||
case 'Point':
|
||||
type = Point;
|
||||
case 'Hinge':
|
||||
type = Hinge;
|
||||
case 'Slider':
|
||||
type = Slider;
|
||||
case 'Piston':
|
||||
type = Piston;
|
||||
case 'Generic Spring':
|
||||
type = Generic;
|
||||
if (con == null) {
|
||||
switch (property0) {
|
||||
case "Fixed": type = Fixed;
|
||||
case "Point": type = Point;
|
||||
case "Hinge": type = Hinge;
|
||||
case "Slider": type = Slider;
|
||||
case "Piston": type = Piston;
|
||||
case "Generic Spring": type = Generic;
|
||||
}
|
||||
|
||||
if(! breakable) breakingThreshold = 0.0;
|
||||
if (!breakable) breakingThreshold = 0.0;
|
||||
|
||||
if (type != Generic) {
|
||||
|
||||
if(type != Generic) {
|
||||
|
||||
con = new PhysicsConstraint(rb1, rb2, type, disableCollisions, breakingThreshold);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case Hinge:
|
||||
var setLimit:Bool = inputs[7].get();
|
||||
var low:Float = inputs[8].get();
|
||||
var up:Float = inputs[9].get();
|
||||
var setLimit: Bool = inputs[7].get();
|
||||
var low: Float = inputs[8].get();
|
||||
var up: Float = inputs[9].get();
|
||||
con.setHingeConstraintLimits(setLimit, low, up);
|
||||
|
||||
case Slider:
|
||||
var setLimit:Bool = inputs[7].get();
|
||||
var low:Float = inputs[8].get();
|
||||
var up:Float = inputs[9].get();
|
||||
var setLimit: Bool = inputs[7].get();
|
||||
var low: Float = inputs[8].get();
|
||||
var up: Float = inputs[9].get();
|
||||
con.setSliderConstraintLimits(setLimit, low, up);
|
||||
|
||||
case Piston:
|
||||
var setLinLimit:Bool = inputs[7].get();
|
||||
var linLow:Float = inputs[8].get();
|
||||
var linUp:Float = inputs[9].get();
|
||||
var setAngLimit:Bool = inputs[10].get();
|
||||
var angLow:Float = inputs[11].get();
|
||||
var angUp:Float = inputs[12].get();
|
||||
var setLinLimit: Bool = inputs[7].get();
|
||||
var linLow: Float = inputs[8].get();
|
||||
var linUp: Float = inputs[9].get();
|
||||
var setAngLimit: Bool = inputs[10].get();
|
||||
var angLow: Float = inputs[11].get();
|
||||
var angUp: Float = inputs[12].get();
|
||||
con.setPistonConstraintLimits(setLinLimit, linLow, linUp, setAngLimit, angLow, angUp);
|
||||
|
||||
default:
|
||||
default:
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
var spring: Bool = false;
|
||||
var prop: PhysicsConstraintNode;
|
||||
for(inp in 7...inputs.length)
|
||||
{
|
||||
|
||||
for (inp in 7...inputs.length) {
|
||||
prop = inputs[inp].get();
|
||||
if(prop == null) continue;
|
||||
if(prop.isSpring)
|
||||
{
|
||||
if (prop == null) continue;
|
||||
if (prop.isSpring) {
|
||||
spring = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(spring) {
|
||||
if (spring) {
|
||||
con = new PhysicsConstraint(rb1, rb2, GenericSpring, disableCollisions, breakingThreshold);
|
||||
}
|
||||
}
|
||||
else {
|
||||
con = new PhysicsConstraint(rb1, rb2, Generic, disableCollisions, breakingThreshold);
|
||||
}
|
||||
|
||||
for(inp in 7...inputs.length)
|
||||
{
|
||||
for (inp in 7...inputs.length) {
|
||||
prop = inputs[inp].get();
|
||||
if(prop == null) continue;
|
||||
(inp + ': ');
|
||||
if (prop == null) continue;
|
||||
|
||||
if(prop.isSpring)
|
||||
{
|
||||
if (prop.isSpring) {
|
||||
con.setSpringParams(prop.isSpring, prop.value1, prop.value2, prop.axis, prop.isAngular);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
con.setGenericConstraintLimits(true, prop.value1, prop.value2, prop.axis, prop.isAngular);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
pivotObject.addTrait(con);
|
||||
|
||||
}
|
||||
#end
|
||||
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package armory.logicnode;
|
||||
|
||||
import iron.object.Object;
|
||||
|
||||
#if arm_physics
|
||||
import armory.trait.physics.RigidBody;
|
||||
import armory.trait.physics.bullet.RigidBody.Shape;
|
||||
#end
|
||||
import iron.object.Object;
|
||||
import armory.trait.physics.RigidBody;
|
||||
|
||||
|
||||
class AddRigidBodyNode extends LogicNode {
|
||||
|
||||
public var property0: String;//Shape
|
||||
public var property1: String;//Advanced
|
||||
public var property0: String; //Shape
|
||||
public var property1: Bool; //Advanced
|
||||
public var object: Object;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
|
@ -18,6 +20,10 @@ class AddRigidBodyNode extends LogicNode {
|
|||
|
||||
override function run(from: Int) {
|
||||
object = inputs[1].get();
|
||||
if (object == null) return;
|
||||
|
||||
#if arm_physics
|
||||
|
||||
var mass: Float = inputs[2].get();
|
||||
var active: Bool = inputs[3].get();
|
||||
var animated: Bool = inputs[4].get();
|
||||
|
@ -38,8 +44,7 @@ class AddRigidBodyNode extends LogicNode {
|
|||
|
||||
var shape: Shape = 1;
|
||||
|
||||
if(property1 == 'true')
|
||||
{
|
||||
if (property1) {
|
||||
margin = inputs[9].get();
|
||||
marginLen = inputs[10].get();
|
||||
linDamp = inputs[11].get();
|
||||
|
@ -49,50 +54,34 @@ class AddRigidBodyNode extends LogicNode {
|
|||
angVelThreshold = inputs[15].get();
|
||||
group = inputs[16].get();
|
||||
mask = inputs[17].get();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (object == null) return;
|
||||
|
||||
#if arm_physics
|
||||
var rb: RigidBody = object.getTrait(RigidBody);
|
||||
if((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
|
||||
if((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
|
||||
if(rb == null)
|
||||
{
|
||||
|
||||
switch (property0){
|
||||
|
||||
case 'Box':
|
||||
shape = Box;
|
||||
case 'Sphere':
|
||||
shape = Sphere;
|
||||
case 'Capsule':
|
||||
shape = Capsule;
|
||||
case 'Cone':
|
||||
shape = Cone;
|
||||
case 'Cylinder':
|
||||
shape = Cylinder;
|
||||
case 'Convex Hull':
|
||||
shape = ConvexHull;
|
||||
case 'Mesh':
|
||||
shape = Mesh;
|
||||
if ((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
|
||||
if ((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
|
||||
if (rb == null) {
|
||||
switch (property0) {
|
||||
case "Box": shape = Box;
|
||||
case "Sphere": shape = Sphere;
|
||||
case "Capsule": shape = Capsule;
|
||||
case "Cone": shape = Cone;
|
||||
case "Cylinder": shape = Cylinder;
|
||||
case "Convex Hull": shape = ConvexHull;
|
||||
case "Mesh": shape = Mesh;
|
||||
}
|
||||
|
||||
rb = new RigidBody(shape, mass, friction, bounciness, group, mask);
|
||||
rb.animated = animated;
|
||||
rb.staticObj = ! active;
|
||||
rb.staticObj = !active;
|
||||
rb.isTriggerObject(trigger);
|
||||
if(property1 == 'true')
|
||||
{
|
||||
|
||||
if (property1) {
|
||||
rb.linearDamping = linDamp;
|
||||
rb.angularDamping = angDamp;
|
||||
if(margin) rb.collisionMargin = marginLen;
|
||||
if(useDeactiv) {
|
||||
if (margin) rb.collisionMargin = marginLen;
|
||||
if (useDeactiv) {
|
||||
rb.setUpDeactivation(true, linearVelThreshold, angVelThreshold, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object.addTrait(rb);
|
||||
|
|
|
@ -1,31 +1,136 @@
|
|||
package armory.logicnode;
|
||||
|
||||
#if arm_patch @:keep @:keepSub #end
|
||||
class LogicNode {
|
||||
|
||||
var tree: LogicTree;
|
||||
var inputs: Array<LogicNodeInput> = [];
|
||||
var outputs: Array<Array<LogicNode>> = [];
|
||||
var inputs: Array<LogicNodeLink> = [];
|
||||
var outputs: Array<Array<LogicNodeLink>> = [];
|
||||
|
||||
#if arm_debug
|
||||
#if (arm_debug || arm_patch)
|
||||
public var name = "";
|
||||
public function watch(b: Bool) { // Watch in debug console
|
||||
var nodes = armory.trait.internal.DebugConsole.watchNodes;
|
||||
b ? nodes.push(this) : nodes.remove(this);
|
||||
}
|
||||
|
||||
#if (arm_debug)
|
||||
public function watch(b: Bool) { // Watch in debug console
|
||||
var nodes = armory.trait.internal.DebugConsole.watchNodes;
|
||||
b ? nodes.push(this) : nodes.remove(this);
|
||||
}
|
||||
#end
|
||||
#end
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
this.tree = tree;
|
||||
}
|
||||
|
||||
public function addInput(node: LogicNode, from: Int) {
|
||||
inputs.push(new LogicNodeInput(node, from));
|
||||
/**
|
||||
Resize the inputs array to a given size to minimize dynamic
|
||||
reallocation and over-allocation later.
|
||||
**/
|
||||
inline function preallocInputs(amount: Int) {
|
||||
this.inputs.resize(amount);
|
||||
}
|
||||
|
||||
public function addOutputs(nodes: Array<LogicNode>) {
|
||||
outputs.push(nodes);
|
||||
/**
|
||||
Resize the outputs array to a given size to minimize dynamic
|
||||
reallocation and over-allocation later.
|
||||
**/
|
||||
inline function preallocOutputs(amount: Int) {
|
||||
this.outputs.resize(amount);
|
||||
for (i in 0...outputs.length) {
|
||||
outputs[i] = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add a link between to nodes to the tree.
|
||||
**/
|
||||
public static function addLink(fromNode: LogicNode, toNode: LogicNode, fromIndex: Int, toIndex: Int): LogicNodeLink {
|
||||
var link = new LogicNodeLink(fromNode, toNode, fromIndex, toIndex);
|
||||
|
||||
if (toNode.inputs.length <= toIndex) {
|
||||
toNode.inputs.resize(toIndex + 1);
|
||||
}
|
||||
toNode.inputs[toIndex] = link;
|
||||
|
||||
var fromNodeOuts = fromNode.outputs;
|
||||
var outLen = fromNodeOuts.length;
|
||||
if (outLen <= fromIndex) {
|
||||
fromNodeOuts.resize(fromIndex + 1);
|
||||
|
||||
// Initialize with empty arrays
|
||||
for (i in outLen...fromIndex + 1) {
|
||||
fromNodeOuts[i] = [];
|
||||
}
|
||||
}
|
||||
fromNodeOuts[fromIndex].push(link);
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
#if arm_patch
|
||||
/**
|
||||
Removes a link from the tree.
|
||||
**/
|
||||
static function removeLink(link: LogicNodeLink) {
|
||||
link.fromNode.outputs[link.fromIndex].remove(link);
|
||||
|
||||
// Reuse the same link and connect a default input node to it.
|
||||
// That's why this function is only available in arm_patch mode, we need
|
||||
// access to the link's type and value.
|
||||
link.fromNode = LogicNode.createSocketDefaultNode(link.toNode.tree, link.toType, link.toValue);
|
||||
link.fromIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all inputs and their links from this node.
|
||||
Warning: this function changes the amount of node inputs to 0!
|
||||
**/
|
||||
function clearInputs() {
|
||||
for (link in inputs) {
|
||||
link.fromNode.outputs[link.fromIndex].remove(link);
|
||||
}
|
||||
inputs.resize(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all outputs and their links from this node.
|
||||
Warning: this function changes the amount of node inputs to 0!
|
||||
**/
|
||||
function clearOutputs() {
|
||||
for (links in outputs) {
|
||||
for (link in links) {
|
||||
var defaultNode = LogicNode.createSocketDefaultNode(tree, link.toType, link.toValue);
|
||||
link.fromNode = defaultNode;
|
||||
link.fromIndex = 0;
|
||||
defaultNode.outputs[0] = [link];
|
||||
}
|
||||
}
|
||||
outputs.resize(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a default node for a socket so that get() and set() can be
|
||||
used without null checks.
|
||||
Loosely equivalent to `make_logic.build_default_node()` in Python.
|
||||
**/
|
||||
static inline function createSocketDefaultNode(tree: LogicTree, socketType: String, value: Dynamic): LogicNode {
|
||||
// Make sure to not add these nodes to the LogicTree.nodes array as they
|
||||
// won't be garbage collected then if unlinked later.
|
||||
return switch (socketType) {
|
||||
case "VECTOR": new armory.logicnode.VectorNode(tree, value[0], value[1], value[2]);
|
||||
case "RGBA": new armory.logicnode.ColorNode(tree, value[0], value[1], value[2], value[3]);
|
||||
case "RGB": new armory.logicnode.ColorNode(tree, value[0], value[1], value[2]);
|
||||
case "VALUE": new armory.logicnode.FloatNode(tree, value);
|
||||
case "INT": new armory.logicnode.IntegerNode(tree, value);
|
||||
case "BOOLEAN": new armory.logicnode.BooleanNode(tree, value);
|
||||
case "STRING": new armory.logicnode.StringNode(tree, value);
|
||||
case "NONE": new armory.logicnode.NullNode(tree);
|
||||
case "OBJECT": new armory.logicnode.ObjectNode(tree, value);
|
||||
default: new armory.logicnode.DynamicNode(tree, value);
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
Called when this node is activated.
|
||||
@param from impulse index
|
||||
|
@ -38,47 +143,45 @@ class LogicNode {
|
|||
**/
|
||||
function runOutput(i: Int) {
|
||||
if (i >= outputs.length) return;
|
||||
for (output in outputs[i]) {
|
||||
// Check which input activated the node
|
||||
for (j in 0...output.inputs.length) {
|
||||
// Check if the node is connected to the current node
|
||||
if (output.inputs[j].node == this) {
|
||||
// Check if the input socekt is linked to current output socket
|
||||
if (output.inputs[j].from == i) {
|
||||
output.run(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (outLink in outputs[i]) {
|
||||
outLink.toNode.run(outLink.toIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@:allow(armory.logicnode.LogicNodeInput)
|
||||
@:allow(armory.logicnode.LogicNodeLink)
|
||||
function get(from: Int): Dynamic { return this; }
|
||||
|
||||
@:allow(armory.logicnode.LogicNodeInput)
|
||||
@:allow(armory.logicnode.LogicNodeLink)
|
||||
function set(value: Dynamic) {}
|
||||
}
|
||||
|
||||
class LogicNodeInput {
|
||||
@:allow(armory.logicnode.LogicNode)
|
||||
@:allow(armory.logicnode.LogicTree)
|
||||
class LogicNodeLink {
|
||||
|
||||
@:allow(armory.logicnode.LogicNode)
|
||||
var node: LogicNode;
|
||||
@:allow(armory.logicnode.LogicNode)
|
||||
var from: Int; // Socket index
|
||||
var fromNode: LogicNode;
|
||||
var toNode: LogicNode;
|
||||
var fromIndex: Int;
|
||||
var toIndex: Int;
|
||||
|
||||
public function new(node: LogicNode, from: Int) {
|
||||
this.node = node;
|
||||
this.from = from;
|
||||
#if arm_patch
|
||||
var fromType: String;
|
||||
var toType: String;
|
||||
var toValue: Dynamic;
|
||||
#end
|
||||
|
||||
inline function new(fromNode: LogicNode, toNode: LogicNode, fromIndex: Int, toIndex: Int) {
|
||||
this.fromNode = fromNode;
|
||||
this.toNode = toNode;
|
||||
this.fromIndex = fromIndex;
|
||||
this.toIndex = toIndex;
|
||||
}
|
||||
|
||||
@:allow(armory.logicnode.LogicNode)
|
||||
function get(): Dynamic {
|
||||
return node.get(from);
|
||||
inline function get(): Dynamic {
|
||||
return fromNode.get(fromIndex);
|
||||
}
|
||||
|
||||
@:allow(armory.logicnode.LogicNode)
|
||||
function set(value: Dynamic) {
|
||||
node.set(value);
|
||||
inline function set(value: Dynamic) {
|
||||
fromNode.set(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,26 @@ package armory.logicnode;
|
|||
|
||||
class LogicTree extends iron.Trait {
|
||||
|
||||
#if arm_patch
|
||||
/**
|
||||
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.
|
||||
**/
|
||||
public var nodes: Map<String, LogicNode>;
|
||||
#end
|
||||
|
||||
public var loopBreak = false; // Trigger break from loop nodes
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
#if arm_patch
|
||||
nodes = new Map<String, LogicNode>();
|
||||
#end
|
||||
}
|
||||
|
||||
public function add() {}
|
||||
|
|
|
@ -3,7 +3,7 @@ package armory.logicnode;
|
|||
class MathNode extends LogicNode {
|
||||
|
||||
public var property0: String; // Operation
|
||||
public var property1: String; // Clamp
|
||||
public var property1: Bool; // Clamp
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
|
@ -80,8 +80,8 @@ class MathNode extends LogicNode {
|
|||
}
|
||||
}
|
||||
// Clamp
|
||||
if (property1 == "true") r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);
|
||||
if (property1) r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ class MixNode extends LogicNode {
|
|||
|
||||
public var property0: String; // Type
|
||||
public var property1: String; // Ease
|
||||
public var property2: String; // Clamp
|
||||
public var property2: Bool; // Clamp
|
||||
|
||||
var ease: Float->Float = null;
|
||||
|
||||
|
@ -50,7 +50,9 @@ class MixNode extends LogicNode {
|
|||
var v2: Float = inputs[2].get();
|
||||
var f = v1 + (v2 - v1) * ease(k);
|
||||
|
||||
if (property2 == "true") f = f < 0 ? 0 : f > 1 ? 1 : f;
|
||||
// Clamp
|
||||
if (property2) f = f < 0 ? 0 : f > 1 ? 1 : f;
|
||||
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ class ObjectNode extends LogicNode {
|
|||
override function set(value: Dynamic) {
|
||||
if (inputs.length > 0) inputs[0].set(value);
|
||||
else {
|
||||
objectName = value.name;
|
||||
objectName = value != null ? value.name : "";
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,50 +3,39 @@ package armory.logicnode;
|
|||
#if arm_physics
|
||||
import armory.trait.physics.bullet.PhysicsConstraint.ConstraintAxis;
|
||||
#end
|
||||
import iron.object.Object;
|
||||
|
||||
class PhysicsConstraintNode extends LogicNode {
|
||||
|
||||
public var property0: String;//Linear or Angular
|
||||
public var property1: String;//Axis
|
||||
public var property2: String;//Is a spring
|
||||
public var value1: Float;//Lower limit or Spring Stiffness
|
||||
public var value2: Float;//Upper limit or Spring Damping
|
||||
public var property0: String; //Linear or Angular
|
||||
public var property1: String; //Axis
|
||||
public var property2: Bool; //Is a spring
|
||||
|
||||
#if arm_physics
|
||||
public var value1: Float; //Lower limit or Spring Stiffness
|
||||
public var value2: Float; //Upper limit or Spring Damping
|
||||
public var isAngular: Bool;
|
||||
public var axis: ConstraintAxis;
|
||||
public var isSpring: Bool;
|
||||
#end
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): PhysicsConstraintNode {
|
||||
#if arm_physics
|
||||
value1 = inputs[0].get();
|
||||
value2 = inputs[1].get();
|
||||
|
||||
if(property0 == 'Linear') {
|
||||
isAngular = false;
|
||||
}
|
||||
else{
|
||||
isAngular = true;
|
||||
}
|
||||
isAngular = property0 != "Linear";
|
||||
isSpring = property2;
|
||||
|
||||
if(property2 == 'true'){
|
||||
isSpring = true;
|
||||
switch (property1) {
|
||||
case "X": axis = X;
|
||||
case "Y": axis = Y;
|
||||
case "Z": axis = Z;
|
||||
}
|
||||
else {
|
||||
isSpring = false;
|
||||
}
|
||||
|
||||
switch (property1){
|
||||
case 'X':
|
||||
axis = X;
|
||||
case 'Y':
|
||||
axis = Y;
|
||||
case 'Z':
|
||||
axis = Z;
|
||||
}
|
||||
|
||||
#end
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ class QuaternionNode extends LogicNode {
|
|||
super(tree);
|
||||
|
||||
if (x != null) {
|
||||
addInput(new FloatNode(tree, x), 0);
|
||||
addInput(new FloatNode(tree, y), 0);
|
||||
addInput(new FloatNode(tree, z), 0);
|
||||
addInput(new FloatNode(tree, w), 0);
|
||||
LogicNode.addLink(new FloatNode(tree, x), this, 0, 0);
|
||||
LogicNode.addLink(new FloatNode(tree, y), this, 0, 1);
|
||||
LogicNode.addLink(new FloatNode(tree, z), this, 0, 2);
|
||||
LogicNode.addLink(new FloatNode(tree, w), this, 0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,15 +27,15 @@ class QuaternionNode extends LogicNode {
|
|||
switch (from){
|
||||
case 0:
|
||||
return value;
|
||||
case 1:
|
||||
var value1 = new Vec4();
|
||||
case 1:
|
||||
var value1 = new Vec4();
|
||||
value1.x = value.x;
|
||||
value1.y = value.y;
|
||||
value1.z = value.z;
|
||||
value1.w = 0; // use 0 to avoid this vector being translated.
|
||||
return value1;
|
||||
case 2:
|
||||
return value.w;
|
||||
return value.w;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ class SetParentNode extends LogicNode {
|
|||
|
||||
var parent: Object;
|
||||
var isUnparent = false;
|
||||
if (Std.isOfType(inputs[2].node, ObjectNode)) {
|
||||
var parentNode = cast(inputs[2].node, ObjectNode);
|
||||
|
||||
if (Std.isOfType(inputs[2].fromNode, ObjectNode)) {
|
||||
var parentNode = cast(inputs[2].fromNode, ObjectNode);
|
||||
isUnparent = parentNode.objectName == "";
|
||||
}
|
||||
if (isUnparent) parent = iron.Scene.active.root;
|
||||
|
@ -24,7 +25,7 @@ class SetParentNode extends LogicNode {
|
|||
if (object == null || parent == null || object.parent == parent) return;
|
||||
|
||||
object.parent.removeChild(object, isUnparent); // keepTransform
|
||||
|
||||
|
||||
#if arm_physics
|
||||
var rigidBody = object.getTrait(RigidBody);
|
||||
if (rigidBody != null) rigidBody.setActivationState(0);
|
||||
|
|
|
@ -7,7 +7,7 @@ class VectorMixNode extends LogicNode {
|
|||
|
||||
public var property0: String; // Type
|
||||
public var property1: String; // Ease
|
||||
public var property2: String; // Clamp
|
||||
public var property2: Bool; // Clamp
|
||||
|
||||
var v = new Vec4();
|
||||
|
||||
|
@ -57,7 +57,7 @@ class VectorMixNode extends LogicNode {
|
|||
v.y = v1.y + (v2.y - v1.y) * f;
|
||||
v.z = v1.z + (v2.z - v1.z) * f;
|
||||
|
||||
if (property2 == "true") v.clamp(0, 1);
|
||||
if (property2) v.clamp(0, 1);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ class VectorNode extends LogicNode {
|
|||
super(tree);
|
||||
|
||||
if (x != null) {
|
||||
addInput(new FloatNode(tree, x), 0);
|
||||
addInput(new FloatNode(tree, y), 0);
|
||||
addInput(new FloatNode(tree, z), 0);
|
||||
LogicNode.addLink(new FloatNode(tree, x), this, 0, 0);
|
||||
LogicNode.addLink(new FloatNode(tree, y), this, 0, 1);
|
||||
LogicNode.addLink(new FloatNode(tree, z), this, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ class Bridge {
|
|||
public static var Input = iron.system.Input;
|
||||
public static var Object = iron.object.Object;
|
||||
public static var Data = iron.data.Data;
|
||||
public static var Vec4 = iron.math.Vec4;
|
||||
public static function log(s: String) { trace(s); };
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
package armory.trait.internal;
|
||||
|
||||
import armory.logicnode.LogicNode;
|
||||
import armory.logicnode.LogicTree;
|
||||
|
||||
|
||||
#if arm_patch @:expose("LivePatch") #end
|
||||
@:access(armory.logicnode.LogicNode)
|
||||
@:access(armory.logicnode.LogicNodeLink)
|
||||
class LivePatch extends iron.Trait {
|
||||
|
||||
#if arm_patch
|
||||
#if !arm_patch
|
||||
public function new() { super(); }
|
||||
#else
|
||||
|
||||
static var patchId = 0;
|
||||
|
||||
|
@ -23,9 +32,164 @@ class LivePatch extends iron.Trait {
|
|||
});
|
||||
}
|
||||
|
||||
#else
|
||||
public static function patchCreateNodeLink(treeName: String, fromNodeName: String, toNodeName: String, fromIndex: Int, toIndex: Int) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
public function new() { super(); }
|
||||
for (tree in trees) {
|
||||
var fromNode = tree.nodes[fromNodeName];
|
||||
var toNode = tree.nodes[toNodeName];
|
||||
if (fromNode == null || toNode == null) return;
|
||||
|
||||
LogicNode.addLink(fromNode, toNode, fromIndex, toIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public static function patchSetNodeLinks(treeName: String, nodeName: String, inputDatas: Array<Dynamic>, outputDatas: Array<Array<Dynamic>>) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
var node = tree.nodes[nodeName];
|
||||
if (node == null) return;
|
||||
|
||||
node.clearInputs();
|
||||
node.clearOutputs();
|
||||
|
||||
for (inputData in inputDatas) {
|
||||
var fromNode: LogicNode;
|
||||
var fromIndex: Int;
|
||||
|
||||
if (inputData.isLinked) {
|
||||
fromNode = tree.nodes[inputData.fromNode];
|
||||
if (fromNode == null) continue;
|
||||
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 {
|
||||
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) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
var node = tree.nodes[nodeName];
|
||||
if (node == null) return;
|
||||
|
||||
Reflect.setField(node, propName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function patchUpdateNodeInputVal(treeName: String, nodeName: String, socketIndex: Int, value: Dynamic) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
var node = tree.nodes[nodeName];
|
||||
if (node == null) return;
|
||||
|
||||
node.inputs[socketIndex].set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function patchNodeDelete(treeName: String, nodeName: String) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
var node = tree.nodes[nodeName];
|
||||
if (node == null) return;
|
||||
|
||||
node.clearOutputs();
|
||||
node.clearInputs();
|
||||
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>>) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
// No further constructor parameters required here, all variable nodes
|
||||
// use optional further parameters and all values are set later in this
|
||||
// function.
|
||||
var newNode: LogicNode = Type.createInstance(Type.resolveClass(nodeType), [tree]);
|
||||
newNode.name = nodeName;
|
||||
tree.nodes[nodeName] = newNode;
|
||||
|
||||
for (propData in propDatas) {
|
||||
Reflect.setField(newNode, propData[0], propData[1]);
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
for (inputData in inputDatas) {
|
||||
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (outputData in outputDatas) {
|
||||
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>>) {
|
||||
if (!LogicTree.nodeTrees.exists(treeName)) return;
|
||||
var trees = LogicTree.nodeTrees[treeName];
|
||||
|
||||
for (tree in trees) {
|
||||
var node = tree.nodes[nodeName];
|
||||
if (node == null) return;
|
||||
|
||||
// No further constructor parameters required here, all variable nodes
|
||||
// use optional further parameters and all values are set later in this
|
||||
// function.
|
||||
var newNode: LogicNode = Type.createInstance(Type.getClass(node), [tree]);
|
||||
newNode.name = newNodeName;
|
||||
tree.nodes[newNodeName] = newNode;
|
||||
|
||||
for (propName in copyProps) {
|
||||
Reflect.setField(newNode, propName, Reflect.field(node, propName));
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
for (inputData in inputDatas) {
|
||||
LogicNode.addLink(LogicNode.createSocketDefaultNode(newNode.tree, inputData[0], inputData[1]), newNode, 0, i++);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (outputData in outputDatas) {
|
||||
LogicNode.addLink(newNode, LogicNode.createSocketDefaultNode(newNode.tree, outputData[0], outputData[1]), i++, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#end
|
||||
}
|
||||
|
|
|
@ -1531,24 +1531,18 @@ Make sure the mesh only has tris/quads.""")
|
|||
# Less bias for bigger maps
|
||||
out_light['shadows_bias'] *= 1 / (out_light['shadowmap_size'] / 1024)
|
||||
elif objtype == 'POINT':
|
||||
out_light['strength'] *= 2.6
|
||||
if bpy.app.version >= (2, 80, 72):
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['fov'] = 1.5708 # pi/2
|
||||
out_light['shadowmap_cube'] = True
|
||||
if light_ref.shadow_soft_size > 0.1:
|
||||
out_light['light_size'] = light_ref.shadow_soft_size * 10
|
||||
elif objtype == 'SPOT':
|
||||
out_light['strength'] *= 2.6
|
||||
if bpy.app.version >= (2, 80, 72):
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['spot_size'] = math.cos(light_ref.spot_size / 2)
|
||||
# Cycles defaults to 0.15
|
||||
out_light['spot_blend'] = light_ref.spot_blend / 10
|
||||
elif objtype == 'AREA':
|
||||
out_light['strength'] *= 80.0 / (light_ref.size * light_ref.size_y)
|
||||
if bpy.app.version >= (2, 80, 72):
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['strength'] *= 0.01
|
||||
out_light['size'] = light_ref.size
|
||||
out_light['size_y'] = light_ref.size_y
|
||||
|
||||
|
@ -2460,7 +2454,7 @@ Make sure the mesh only has tris/quads.""")
|
|||
else:
|
||||
self.material_to_object_dict[mat] = [bobject]
|
||||
self.material_to_arm_object_dict[mat] = [o]
|
||||
|
||||
|
||||
# Add UniformsManager trait
|
||||
if type is NodeType.MESH:
|
||||
uniformManager = {}
|
||||
|
@ -2678,7 +2672,7 @@ Make sure the mesh only has tris/quads.""")
|
|||
}
|
||||
self.output['traits'].append(out_trait)
|
||||
|
||||
if wrd.arm_live_patch:
|
||||
if arm.utils.is_livepatch_enabled():
|
||||
if 'traits' not in self.output:
|
||||
self.output['traits'] = []
|
||||
out_trait = {'type': 'Script', 'class_name': 'armory.trait.internal.LivePatch'}
|
||||
|
|
|
@ -7,6 +7,7 @@ import bpy
|
|||
from bpy.app.handlers import persistent
|
||||
|
||||
import arm.api
|
||||
import arm.live_patch as live_patch
|
||||
import arm.logicnode.arm_nodes as arm_nodes
|
||||
import arm.nodes_logic
|
||||
import arm.make as make
|
||||
|
@ -14,6 +15,7 @@ import arm.make_state as state
|
|||
import arm.props as props
|
||||
import arm.utils
|
||||
|
||||
|
||||
@persistent
|
||||
def on_depsgraph_update_post(self):
|
||||
if state.proc_build != None:
|
||||
|
@ -41,12 +43,10 @@ def on_depsgraph_update_post(self):
|
|||
|
||||
# Send last operator to Krom
|
||||
wrd = bpy.data.worlds['Arm']
|
||||
if state.proc_play != None and \
|
||||
state.target == 'krom' and \
|
||||
wrd.arm_live_patch:
|
||||
if state.proc_play is not None and state.target == 'krom' and wrd.arm_live_patch:
|
||||
ops = bpy.context.window_manager.operators
|
||||
if len(ops) > 0 and ops[-1] != None:
|
||||
send_operator(ops[-1])
|
||||
if len(ops) > 0 and ops[-1] is not None:
|
||||
live_patch.on_operator(ops[-1].bl_idname)
|
||||
|
||||
# Hacky solution to update armory props after operator executions
|
||||
last_operator = bpy.context.active_operator
|
||||
|
@ -125,6 +125,7 @@ def poll_threads() -> float:
|
|||
appended_py_paths = []
|
||||
context_screen = None
|
||||
|
||||
|
||||
@persistent
|
||||
def on_load_post(context):
|
||||
global appended_py_paths
|
||||
|
|
376
blender/arm/live_patch.py
Normal file
376
blender/arm/live_patch.py
Normal file
|
@ -0,0 +1,376 @@
|
|||
import os
|
||||
import shutil
|
||||
from typing import Any, Type
|
||||
|
||||
import bpy
|
||||
|
||||
import arm.assets
|
||||
import arm.node_utils
|
||||
from arm.exporter import ArmoryExporter
|
||||
import arm.log as log
|
||||
from arm.logicnode.arm_nodes import ArmLogicTreeNode
|
||||
import arm.make as make
|
||||
import arm.make_state as state
|
||||
import arm.utils
|
||||
|
||||
# Current patch id
|
||||
patch_id = 0
|
||||
|
||||
# Any object can act as a message bus owner
|
||||
msgbus_owner = object()
|
||||
|
||||
# Whether live patch is currently active
|
||||
__running = False
|
||||
|
||||
|
||||
def start():
|
||||
"""Start the live patch session."""
|
||||
log.debug("Live patch session started")
|
||||
|
||||
listen(bpy.types.Object, "location", "obj_location")
|
||||
listen(bpy.types.Object, "rotation_euler", "obj_rotation")
|
||||
listen(bpy.types.Object, "scale", "obj_scale")
|
||||
|
||||
# 'energy' is defined in sub classes only, also workaround for
|
||||
# https://developer.blender.org/T88408
|
||||
for light_type in (bpy.types.AreaLight, bpy.types.PointLight, bpy.types.SpotLight, bpy.types.SunLight):
|
||||
listen(light_type, "color", "light_color")
|
||||
listen(light_type, "energy", "light_energy")
|
||||
|
||||
global __running
|
||||
__running = True
|
||||
|
||||
|
||||
def stop():
|
||||
"""Stop the live patch session."""
|
||||
global __running
|
||||
if __running:
|
||||
__running = False
|
||||
|
||||
log.debug("Live patch session stopped")
|
||||
bpy.msgbus.clear_by_owner(msgbus_owner)
|
||||
|
||||
|
||||
def patch_export():
|
||||
"""Re-export the current scene and update the game accordingly."""
|
||||
if not __running or state.proc_build is not None:
|
||||
return
|
||||
|
||||
arm.assets.invalidate_enabled = False
|
||||
|
||||
with arm.utils.WorkingDir(arm.utils.get_fp()):
|
||||
asset_path = arm.utils.get_fp_build() + '/compiled/Assets/' + arm.utils.safestr(bpy.context.scene.name) + '.arm'
|
||||
ArmoryExporter.export_scene(bpy.context, asset_path, scene=bpy.context.scene)
|
||||
|
||||
dir_std_shaders_dst = os.path.join(arm.utils.build_dir(), 'compiled', 'Shaders', 'std')
|
||||
if not os.path.isdir(dir_std_shaders_dst):
|
||||
dir_std_shaders_src = os.path.join(arm.utils.get_sdk_path(), 'armory', 'Shaders', 'std')
|
||||
shutil.copytree(dir_std_shaders_src, dir_std_shaders_dst)
|
||||
|
||||
node_path = arm.utils.get_node_path()
|
||||
khamake_path = arm.utils.get_khamake_path()
|
||||
cmd = [
|
||||
node_path, khamake_path, 'krom',
|
||||
'--shaderversion', '330',
|
||||
'--parallelAssetConversion', '4',
|
||||
'--to', arm.utils.build_dir() + '/debug',
|
||||
'--nohaxe',
|
||||
'--noproject'
|
||||
]
|
||||
|
||||
arm.assets.invalidate_enabled = True
|
||||
state.proc_build = make.run_proc(cmd, patch_done)
|
||||
|
||||
|
||||
def patch_done():
|
||||
"""Signal Iron to reload the running scene after a re-export."""
|
||||
js = 'iron.Scene.patch();'
|
||||
write_patch(js)
|
||||
state.proc_build = None
|
||||
|
||||
|
||||
def write_patch(js: str):
|
||||
"""Write the given javascript code to 'krom.patch'."""
|
||||
global patch_id
|
||||
with open(arm.utils.get_fp_build() + '/debug/krom/krom.patch', 'w') as f:
|
||||
patch_id += 1
|
||||
f.write(str(patch_id) + '\n')
|
||||
f.write(js)
|
||||
|
||||
|
||||
def listen(rna_type: Type[bpy.types.bpy_struct], prop: str, event_id: str):
|
||||
"""Subscribe to '<rna_type>.<prop>'. The event_id can be choosen
|
||||
freely but must match with the id used in send_event().
|
||||
"""
|
||||
bpy.msgbus.subscribe_rna(
|
||||
key=(rna_type, prop),
|
||||
owner=msgbus_owner,
|
||||
args=(event_id, ),
|
||||
notify=send_event
|
||||
# options={"PERSISTENT"}
|
||||
)
|
||||
|
||||
|
||||
def send_event(event_id: str, opt_data: Any = None):
|
||||
"""Send the result of the given event to Krom."""
|
||||
if not __running:
|
||||
return
|
||||
|
||||
if hasattr(bpy.context, 'object') and bpy.context.object is not None:
|
||||
obj = bpy.context.object.name
|
||||
|
||||
if bpy.context.object.mode == "OBJECT":
|
||||
if event_id == "obj_location":
|
||||
vec = bpy.context.object.location
|
||||
js = f'var o = iron.Scene.active.getChild("{obj}"); o.transform.loc.set({vec[0]}, {vec[1]}, {vec[2]}); o.transform.dirty = true;'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'obj_scale':
|
||||
vec = bpy.context.object.scale
|
||||
js = f'var o = iron.Scene.active.getChild("{obj}"); o.transform.scale.set({vec[0]}, {vec[1]}, {vec[2]}); o.transform.dirty = true;'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'obj_rotation':
|
||||
vec = bpy.context.object.rotation_euler.to_quaternion()
|
||||
js = f'var o = iron.Scene.active.getChild("{obj}"); o.transform.rot.set({vec[1]}, {vec[2]}, {vec[3]}, {vec[0]}); o.transform.dirty = true;'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'light_color':
|
||||
light: bpy.types.Light = bpy.context.object.data
|
||||
vec = light.color
|
||||
js = f'var lRaw = iron.Scene.active.getLight("{light.name}").data.raw; lRaw.color[0]={vec[0]}; lRaw.color[1]={vec[1]}; lRaw.color[2]={vec[2]};'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'light_energy':
|
||||
light: bpy.types.Light = bpy.context.object.data
|
||||
|
||||
# Align strength to Armory, see exporter.export_light()
|
||||
# TODO: Use exporter.export_light() and simply reload all raw light data in Iron?
|
||||
strength_fac = 1.0
|
||||
if light.type == 'SUN':
|
||||
strength_fac = 0.325
|
||||
elif light.type in ('POINT', 'SPOT', 'AREA'):
|
||||
strength_fac = 0.01
|
||||
|
||||
js = f'var lRaw = iron.Scene.active.getLight("{light.name}").data.raw; lRaw.strength={light.energy * strength_fac};'
|
||||
write_patch(js)
|
||||
|
||||
else:
|
||||
patch_export()
|
||||
|
||||
if event_id == 'ln_insert_link':
|
||||
node: ArmLogicTreeNode
|
||||
link: bpy.types.NodeLink
|
||||
node, link = opt_data
|
||||
|
||||
# This event is called twice for a connection but we only need
|
||||
# send it once
|
||||
if node == link.from_node:
|
||||
tree_name = arm.node_utils.get_export_tree_name(node.get_tree())
|
||||
|
||||
# [1:] is used here because make_logic already uses that for
|
||||
# node names if arm_debug is used
|
||||
from_node_name = arm.node_utils.get_export_node_name(node)[1:]
|
||||
to_node_name = arm.node_utils.get_export_node_name(link.to_node)[1:]
|
||||
|
||||
from_index = arm.node_utils.get_socket_index(node.outputs, link.from_socket)
|
||||
to_index = arm.node_utils.get_socket_index(link.to_node.inputs, link.to_socket)
|
||||
|
||||
js = f'LivePatch.patchCreateNodeLink("{tree_name}", "{from_node_name}", "{to_node_name}", "{from_index}", "{to_index}");'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'ln_update_prop':
|
||||
node: ArmLogicTreeNode
|
||||
prop_name: str
|
||||
node, prop_name = 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:]
|
||||
|
||||
value = arm.node_utils.haxe_format_prop_value(node, prop_name)
|
||||
|
||||
if prop_name.endswith('_get'):
|
||||
# Hack because some nodes use a different Python property
|
||||
# name than they use in Haxe
|
||||
prop_name = prop_name[:-4]
|
||||
|
||||
js = f'LivePatch.patchUpdateNodeProp("{tree_name}", "{node_name}", "{prop_name}", {value});'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'ln_socket_val':
|
||||
node: ArmLogicTreeNode
|
||||
socket: bpy.types.NodeSocket
|
||||
node, socket = opt_data
|
||||
|
||||
socket_index = arm.node_utils.get_socket_index(node.inputs, socket)
|
||||
|
||||
if socket_index != -1:
|
||||
tree_name = arm.node_utils.get_export_tree_name(node.get_tree())
|
||||
node_name = arm.node_utils.get_export_node_name(node)[1:]
|
||||
|
||||
value = socket.get_default_value()
|
||||
inp_type = socket.arm_socket_type
|
||||
|
||||
if inp_type in ('VECTOR', 'RGB'):
|
||||
value = f'new iron.Vec4({arm.node_utils.haxe_format_socket_val(value, array_outer_brackets=False)}, 1.0)'
|
||||
elif inp_type == 'RGBA':
|
||||
value = f'new iron.Vec4({arm.node_utils.haxe_format_socket_val(value, array_outer_brackets=False)})'
|
||||
elif inp_type == 'OBJECT':
|
||||
value = f'iron.Scene.active.getChild("{value}")' if value != '' else 'null'
|
||||
else:
|
||||
value = arm.node_utils.haxe_format_socket_val(value)
|
||||
|
||||
js = f'LivePatch.patchUpdateNodeInputVal("{tree_name}", "{node_name}", {socket_index}, {value});'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'ln_create':
|
||||
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:]
|
||||
node_type = 'armory.logicnode.' + node.bl_idname[2:]
|
||||
|
||||
prop_names = list(arm.node_utils.get_haxe_property_names(node))
|
||||
prop_py_names, prop_hx_names = zip(*prop_names) if len(prop_names) > 0 else ([], [])
|
||||
prop_values = (getattr(node, prop_name) for prop_name in prop_py_names)
|
||||
prop_datas = arm.node_utils.haxe_format_socket_val(list(zip(prop_hx_names, prop_values)))
|
||||
|
||||
inp_data = [(inp.arm_socket_type, inp.get_default_value()) for inp in node.inputs]
|
||||
inp_data = arm.node_utils.haxe_format_socket_val(inp_data)
|
||||
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.patchNodeCreate("{tree_name}", "{node_name}", "{node_type}", {prop_datas}, {inp_data}, {out_data});'
|
||||
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:]
|
||||
|
||||
js = f'LivePatch.patchNodeDelete("{tree_name}", "{node_name}");'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'ln_copy':
|
||||
newnode: ArmLogicTreeNode
|
||||
node: ArmLogicTreeNode
|
||||
newnode, node = opt_data
|
||||
|
||||
# Use newnode to get the tree, node has no id_data at this moment
|
||||
tree_name = arm.node_utils.get_export_tree_name(newnode.get_tree())
|
||||
|
||||
newnode_name = arm.node_utils.get_export_node_name(newnode)[1:]
|
||||
node_name = arm.node_utils.get_export_node_name(node)[1:]
|
||||
|
||||
props_list = '[' + ','.join(f'"{p}"' for _, p in arm.node_utils.get_haxe_property_names(node)) + ']'
|
||||
|
||||
inp_data = [(inp.arm_socket_type, inp.get_default_value()) for inp in newnode.inputs]
|
||||
inp_data = arm.node_utils.haxe_format_socket_val(inp_data)
|
||||
out_data = [(out.arm_socket_type, out.get_default_value()) for out in newnode.outputs]
|
||||
out_data = arm.node_utils.haxe_format_socket_val(out_data)
|
||||
|
||||
js = f'LivePatch.patchNodeCopy("{tree_name}", "{node_name}", "{newnode_name}", {props_list}, {inp_data}, {out_data});'
|
||||
write_patch(js)
|
||||
|
||||
elif event_id == 'ln_update_sockets':
|
||||
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:]
|
||||
|
||||
inp_data = '['
|
||||
for idx, inp in enumerate(node.inputs):
|
||||
inp_data += '{'
|
||||
# is_linked can be true even if there are no links if the
|
||||
# user starts dragging a connection away before releasing
|
||||
# the mouse
|
||||
if inp.is_linked and len(inp.links) > 0:
|
||||
inp_data += 'isLinked: true,'
|
||||
inp_data += f'fromNode: "{arm.node_utils.get_export_node_name(inp.links[0].from_node)[1:]}",'
|
||||
inp_data += f'fromIndex: {arm.node_utils.get_socket_index(inp.links[0].from_node.outputs, inp.links[0].from_socket)},'
|
||||
else:
|
||||
inp_data += 'isLinked: false,'
|
||||
inp_data += f'socketType: "{inp.arm_socket_type}",'
|
||||
inp_data += f'socketValue: {arm.node_utils.haxe_format_socket_val(inp.get_default_value())},'
|
||||
|
||||
inp_data += f'toIndex: {idx}'
|
||||
inp_data += '},'
|
||||
inp_data += ']'
|
||||
|
||||
out_data = '['
|
||||
for idx, out in enumerate(node.outputs):
|
||||
out_data += '['
|
||||
for link in out.links:
|
||||
out_data += '{'
|
||||
if out.is_linked:
|
||||
out_data += 'isLinked: true,'
|
||||
out_data += f'toNode: "{arm.node_utils.get_export_node_name(link.to_node)[1:]}",'
|
||||
out_data += f'toIndex: {arm.node_utils.get_socket_index(link.to_node.inputs, link.to_socket)},'
|
||||
else:
|
||||
out_data += 'isLinked: false,'
|
||||
out_data += f'socketType: "{out.arm_socket_type}",'
|
||||
out_data += f'socketValue: {arm.node_utils.haxe_format_socket_val(out.get_default_value())},'
|
||||
|
||||
out_data += f'fromIndex: {idx}'
|
||||
out_data += '},'
|
||||
out_data += '],'
|
||||
out_data += ']'
|
||||
|
||||
js = f'LivePatch.patchSetNodeLinks("{tree_name}", "{node_name}", {inp_data}, {out_data});'
|
||||
write_patch(js)
|
||||
|
||||
|
||||
def on_operator(operator_id: str):
|
||||
"""As long as bpy.msgbus doesn't listen to changes made by
|
||||
operators (*), additionally notify the callback manually.
|
||||
|
||||
(*) https://developer.blender.org/T72109
|
||||
"""
|
||||
if not __running:
|
||||
return
|
||||
|
||||
if operator_id in IGNORE_OPERATORS:
|
||||
return
|
||||
|
||||
if operator_id == 'TRANSFORM_OT_translate':
|
||||
send_event('obj_location')
|
||||
elif operator_id in ('TRANSFORM_OT_rotate', 'TRANSFORM_OT_trackball'):
|
||||
send_event('obj_rotation')
|
||||
elif operator_id == 'TRANSFORM_OT_resize':
|
||||
send_event('obj_scale')
|
||||
|
||||
# Rebuild
|
||||
else:
|
||||
patch_export()
|
||||
|
||||
|
||||
# Don't re-export the scene for the following operators
|
||||
IGNORE_OPERATORS = (
|
||||
'ARM_OT_node_add_input',
|
||||
'ARM_OT_node_add_input_output',
|
||||
'ARM_OT_node_add_input_value',
|
||||
'ARM_OT_node_add_output',
|
||||
'ARM_OT_node_call_func',
|
||||
'ARM_OT_node_remove_input',
|
||||
'ARM_OT_node_remove_input_output',
|
||||
'ARM_OT_node_remove_input_value',
|
||||
'ARM_OT_node_remove_output',
|
||||
'ARM_OT_node_search',
|
||||
|
||||
'NODE_OT_delete',
|
||||
'NODE_OT_duplicate_move',
|
||||
'NODE_OT_hide_toggle',
|
||||
'NODE_OT_link',
|
||||
'NODE_OT_move_detach_links',
|
||||
'NODE_OT_select',
|
||||
'NODE_OT_translate_attach',
|
||||
'NODE_OT_translate_attach_remove_on_cancel',
|
||||
|
||||
'OBJECT_OT_editmode_toggle',
|
||||
'OUTLINER_OT_item_activate',
|
||||
'UI_OT_button_string_clear',
|
||||
'UI_OT_eyedropper_id',
|
||||
'VIEW3D_OT_select',
|
||||
'VIEW3D_OT_select_box',
|
||||
)
|
|
@ -6,8 +6,7 @@ class AnimActionNode(ArmLogicTreeNode):
|
|||
bl_label = 'Action'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(AnimActionNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAnimAction', 'Action')
|
||||
|
||||
self.add_output('ArmNodeSocketAnimAction', 'Action', is_var=True)
|
||||
|
|
|
@ -6,12 +6,11 @@ class BlendActionNode(ArmLogicTreeNode):
|
|||
bl_label = 'Blend Action'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(BlendActionNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('ArmNodeSocketAnimAction', 'Action 1')
|
||||
self.add_input('ArmNodeSocketAnimAction', 'Action 2')
|
||||
self.add_input('NodeSocketFloat', 'Factor', default_value = 0.5)
|
||||
self.add_input('ArmFloatSocket', 'Factor', default_value = 0.5)
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -7,11 +7,10 @@ class BoneFKNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(BoneFKNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Bone')
|
||||
self.add_input('NodeSocketShader', 'Transform')
|
||||
self.add_input('ArmStringSocket', 'Bone')
|
||||
self.add_input('ArmDynamicSocket', 'Transform')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -26,19 +26,17 @@ class BoneIKNode(ArmLogicTreeNode):
|
|||
arm_version = 2
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(BoneIKNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Bone')
|
||||
self.add_input('NodeSocketVector', 'Goal Position')
|
||||
self.add_input('NodeSocketBool', 'Enable Pole')
|
||||
self.add_input('NodeSocketVector', 'Pole Position')
|
||||
self.add_input('NodeSocketInt', 'Chain Length')
|
||||
self.add_input('NodeSocketInt', 'Max Iterations', 10)
|
||||
self.add_input('NodeSocketFloat', 'Precision', 0.01)
|
||||
self.add_input('NodeSocketFloat', 'Roll Angle')
|
||||
|
||||
self.add_input('ArmStringSocket', 'Bone')
|
||||
self.add_input('ArmVectorSocket', 'Goal Position')
|
||||
self.add_input('ArmBoolSocket', 'Enable Pole')
|
||||
self.add_input('ArmVectorSocket', 'Pole Position')
|
||||
self.add_input('ArmIntSocket', 'Chain Length')
|
||||
self.add_input('ArmIntSocket', 'Max Iterations', 10)
|
||||
self.add_input('ArmFloatSocket', 'Precision', 0.01)
|
||||
self.add_input('ArmFloatSocket', 'Roll Angle')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
|
|
|
@ -6,10 +6,9 @@ class AnimationStateNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Action State'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(AnimationStateNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
|
||||
self.add_output('NodeSocketString', 'Action')
|
||||
self.add_output('NodeSocketInt', 'Frame')
|
||||
self.add_output('NodeSocketBool', 'Is Paused')
|
||||
self.add_output('ArmStringSocket', 'Action')
|
||||
self.add_output('ArmIntSocket', 'Frame')
|
||||
self.add_output('ArmBoolSocket', 'Is Paused')
|
||||
|
|
|
@ -7,8 +7,7 @@ class GetBoneFkIkOnlyNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(GetBoneFkIkOnlyNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Bone')
|
||||
self.add_output('NodeSocketBool', 'FK or IK only')
|
||||
self.add_input('ArmStringSocket', 'Bone')
|
||||
self.add_output('ArmBoolSocket', 'FK or IK only')
|
||||
|
|
|
@ -7,8 +7,7 @@ class GetBoneTransformNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(GetBoneTransformNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Bone')
|
||||
self.add_output('NodeSocketShader', 'Transform')
|
||||
self.add_input('ArmStringSocket', 'Bone')
|
||||
self.add_output('ArmDynamicSocket', 'Transform')
|
||||
|
|
|
@ -7,10 +7,9 @@ class GetTilesheetStateNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'tilesheet'
|
||||
|
||||
def init(self, context):
|
||||
super(GetTilesheetStateNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
|
||||
self.add_output('NodeSocketString', 'Name')
|
||||
self.add_output('NodeSocketInt', 'Frame')
|
||||
self.add_output('NodeSocketBool', 'Is Paused')
|
||||
self.add_output('ArmStringSocket', 'Name')
|
||||
self.add_output('ArmIntSocket', 'Frame')
|
||||
self.add_output('ArmBoolSocket', 'Is Paused')
|
||||
|
|
|
@ -6,9 +6,8 @@ class OnActionMarkerNode(ArmLogicTreeNode):
|
|||
bl_label = 'On Action Marker'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(OnActionMarkerNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Marker')
|
||||
self.add_input('ArmStringSocket', 'Marker')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,15 +6,14 @@ class PlayActionFromNode(ArmLogicTreeNode):
|
|||
bl_label = 'Play Action From'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(PlayActionFromNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('ArmNodeSocketAnimAction', 'Action')
|
||||
self.add_input('NodeSocketInt', 'Start Frame')
|
||||
self.add_input('NodeSocketFloat', 'Blend', default_value = 0.25)
|
||||
self.add_input('NodeSocketFloat', 'Speed', default_value = 1.0)
|
||||
self.add_input('NodeSocketBool', 'Loop', default_value = False)
|
||||
self.add_input('ArmIntSocket', 'Start Frame')
|
||||
self.add_input('ArmFloatSocket', 'Blend', default_value = 0.25)
|
||||
self.add_input('ArmFloatSocket', 'Speed', default_value = 1.0)
|
||||
self.add_input('ArmBoolSocket', 'Loop', default_value = False)
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('ArmNodeSocketAction', 'Done')
|
||||
|
@ -22,7 +21,7 @@ class PlayActionFromNode(ArmLogicTreeNode):
|
|||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
raise LookupError()
|
||||
|
||||
|
||||
return NodeReplacement(
|
||||
'LNPlayActionFromNode', self.arm_version, 'LNPlayActionFromNode', 2,
|
||||
in_socket_mapping={0:0, 1:1, 2:2, 3:3, 4:4}, out_socket_mapping={0:0, 1:1}
|
||||
|
|
|
@ -7,11 +7,10 @@ class PlayTilesheetNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'tilesheet'
|
||||
|
||||
def init(self, context):
|
||||
super(PlayTilesheetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Name')
|
||||
self.add_input('ArmStringSocket', 'Name')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('ArmNodeSocketAction', 'Done')
|
||||
|
|
|
@ -6,10 +6,9 @@ class SetActionPausedNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Action Paused'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetActionPausedNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketBool', 'Paused')
|
||||
self.add_input('ArmBoolSocket', 'Paused')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class SetActionSpeedNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Action Speed'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetActionSpeedNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketFloat', 'Speed', default_value=1.0)
|
||||
self.add_input('ArmFloatSocket', 'Speed', default_value=1.0)
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -7,11 +7,10 @@ class SetBoneFkIkOnlyNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(SetBoneFkIkOnlyNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketString', 'Bone')
|
||||
self.add_input('NodeSocketBool', 'FK or IK only')
|
||||
self.add_input('ArmStringSocket', 'Bone')
|
||||
self.add_input('ArmBoolSocket', 'FK or IK only')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -7,11 +7,10 @@ class SetParentBoneNode(ArmLogicTreeNode):
|
|||
arm_version = 1
|
||||
arm_section = 'armature'
|
||||
|
||||
def init(self, context):
|
||||
super(SetParentBoneNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('ArmNodeSocketObject', 'Parent', default_value='Parent')
|
||||
self.add_input('NodeSocketString', 'Bone', default_value='Bone')
|
||||
self.add_input('ArmStringSocket', 'Bone', default_value='Bone')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class SetParticleSpeedNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Particle Speed'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetParticleSpeedNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketFloat', 'Speed', default_value=1.0)
|
||||
self.add_input('ArmFloatSocket', 'Speed', default_value=1.0)
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -7,10 +7,9 @@ class SetTilesheetPausedNode(ArmLogicTreeNode):
|
|||
arm_section = 'tilesheet'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetTilesheetPausedNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketBool', 'Paused')
|
||||
self.add_input('ArmBoolSocket', 'Paused')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import itertools
|
||||
from collections import OrderedDict
|
||||
from typing import Any, Generator, List, Optional, Type, Dict
|
||||
from typing import Any, Generator, List, Optional, Type
|
||||
from typing import OrderedDict as ODict # Prevent naming conflicts
|
||||
|
||||
import bpy.types
|
||||
from bpy.props import *
|
||||
from nodeitems_utils import NodeItem
|
||||
|
||||
# Pass NodeReplacment forward to individual node modules that import arm_nodes
|
||||
import arm # we cannot import arm.livepatch here or we have a circular import
|
||||
# Pass custom property types and NodeReplacement forward to individual
|
||||
# node modules that import arm_nodes
|
||||
from arm.logicnode.arm_props import *
|
||||
from arm.logicnode.replacement import NodeReplacement
|
||||
import arm.node_utils
|
||||
|
||||
|
@ -21,6 +24,10 @@ category_items: ODict[str, List['ArmNodeCategory']] = OrderedDict()
|
|||
|
||||
array_nodes = dict()
|
||||
|
||||
# See ArmLogicTreeNode.update()
|
||||
# format: [tree pointer => (num inputs, num input links, num outputs, num output links)]
|
||||
last_node_state: dict[int, tuple[int, int, int, int]] = {}
|
||||
|
||||
|
||||
class ArmLogicTreeNode(bpy.types.Node):
|
||||
arm_category = PKG_AS_CATEGORY
|
||||
|
@ -34,6 +41,14 @@ class ArmLogicTreeNode(bpy.types.Node):
|
|||
else:
|
||||
self.arm_version = 1
|
||||
|
||||
if not hasattr(self, 'arm_init'):
|
||||
# Show warning for older node packages
|
||||
arm.log.warn(f'Node {self.bl_idname} has no arm_init function and might not work correctly!')
|
||||
else:
|
||||
self.arm_init(context)
|
||||
|
||||
arm.live_patch.send_event('ln_create', self)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, ntree):
|
||||
return ntree.bl_idname == 'ArmLogicTreeType'
|
||||
|
@ -48,6 +63,68 @@ class ArmLogicTreeNode(bpy.types.Node):
|
|||
def on_unregister(cls):
|
||||
pass
|
||||
|
||||
def get_tree(self):
|
||||
return self.id_data
|
||||
|
||||
def update(self):
|
||||
"""Called if the node was updated in some way, for example
|
||||
if socket connections change. This callback is not called if
|
||||
socket values were changed.
|
||||
"""
|
||||
def num_connected(sockets):
|
||||
return sum([socket.is_linked for socket in sockets])
|
||||
|
||||
# If a link between sockets is removed, there is currently no
|
||||
# _reliable_ way in the Blender API to check which connection
|
||||
# was removed (*).
|
||||
#
|
||||
# So instead we just check _if_ the number of links or sockets
|
||||
# has changed (the update function is called before and after
|
||||
# each link removal). Because we listen for those updates in
|
||||
# general, we automatically also listen to link creation events,
|
||||
# which is more stable than using the dedicated callback for
|
||||
# that (`insert_link()`), because adding links can remove other
|
||||
# links and we would need to react to that as well.
|
||||
#
|
||||
# (*) https://devtalk.blender.org/t/how-to-detect-which-link-was-deleted-by-user-in-node-editor
|
||||
|
||||
self_id = self.as_pointer()
|
||||
|
||||
current_state = (len(self.inputs), num_connected(self.inputs), len(self.outputs), num_connected(self.outputs))
|
||||
if self_id not in last_node_state:
|
||||
# Lazily initialize the last_node_state dict to also store
|
||||
# state for nodes that already exist in the tree
|
||||
last_node_state[self_id] = current_state
|
||||
|
||||
if last_node_state[self_id] != current_state:
|
||||
arm.live_patch.send_event('ln_update_sockets', self)
|
||||
last_node_state[self_id] = current_state
|
||||
|
||||
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.
|
||||
"""
|
||||
arm.live_patch.send_event('ln_copy', (self, node))
|
||||
|
||||
def on_prop_update(self, context: bpy.types.Context, prop_name: str):
|
||||
"""Called if a property created with a function from the
|
||||
arm_props module is changed. If the property has a custom update
|
||||
function, it is called before `on_prop_update()`.
|
||||
"""
|
||||
arm.live_patch.send_event('ln_update_prop', (self, prop_name))
|
||||
|
||||
def on_socket_val_update(self, context: bpy.types.Context, socket: bpy.types.NodeSocket):
|
||||
arm.live_patch.send_event('ln_socket_val', (self, socket))
|
||||
|
||||
def insert_link(self, link: bpy.types.NodeLink):
|
||||
"""Called on *both* nodes when a link between two nodes is created."""
|
||||
# arm.live_patch.send_event('ln_insert_link', (self, link))
|
||||
pass
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
# needs to be overridden by individual node classes with arm_version>1
|
||||
"""(only called if the node's version is inferior to the node class's version)
|
||||
|
@ -115,7 +192,7 @@ class ArmNodeAddInputButton(bpy.types.Operator):
|
|||
bl_options = {'UNDO', 'INTERNAL'}
|
||||
|
||||
node_index: StringProperty(name='Node Index', default='')
|
||||
socket_type: StringProperty(name='Socket Type', default='NodeSocketShader')
|
||||
socket_type: StringProperty(name='Socket Type', default='ArmDynamicSocket')
|
||||
name_format: StringProperty(name='Name Format', default='Input {0}')
|
||||
index_name_offset: IntProperty(name='Index Name Offset', default=0)
|
||||
|
||||
|
@ -126,7 +203,7 @@ class ArmNodeAddInputButton(bpy.types.Operator):
|
|||
|
||||
# Reset to default again for subsequent calls of this operator
|
||||
self.node_index = ''
|
||||
self.socket_type = 'NodeSocketShader'
|
||||
self.socket_type = 'ArmDynamicSocket'
|
||||
self.name_format = 'Input {0}'
|
||||
self.index_name_offset = 0
|
||||
|
||||
|
@ -138,7 +215,7 @@ class ArmNodeAddInputValueButton(bpy.types.Operator):
|
|||
bl_label = 'Add Input'
|
||||
bl_options = {'UNDO', 'INTERNAL'}
|
||||
node_index: StringProperty(name='Node Index', default='')
|
||||
socket_type: StringProperty(name='Socket Type', default='NodeSocketShader')
|
||||
socket_type: StringProperty(name='Socket Type', default='ArmDynamicSocket')
|
||||
|
||||
def execute(self, context):
|
||||
global array_nodes
|
||||
|
@ -185,7 +262,7 @@ class ArmNodeAddOutputButton(bpy.types.Operator):
|
|||
bl_options = {'UNDO', 'INTERNAL'}
|
||||
|
||||
node_index: StringProperty(name='Node Index', default='')
|
||||
socket_type: StringProperty(name='Socket Type', default='NodeSocketShader')
|
||||
socket_type: StringProperty(name='Socket Type', default='ArmDynamicSocket')
|
||||
name_format: StringProperty(name='Name Format', default='Output {0}')
|
||||
index_name_offset: IntProperty(name='Index Name Offset', default=0)
|
||||
|
||||
|
@ -196,7 +273,7 @@ class ArmNodeAddOutputButton(bpy.types.Operator):
|
|||
|
||||
# Reset to default again for subsequent calls of this operator
|
||||
self.node_index = ''
|
||||
self.socket_type = 'NodeSocketShader'
|
||||
self.socket_type = 'ArmDynamicSocket'
|
||||
self.name_format = 'Output {0}'
|
||||
self.index_name_offset = 0
|
||||
|
||||
|
@ -225,8 +302,8 @@ class ArmNodeAddInputOutputButton(bpy.types.Operator):
|
|||
bl_options = {'UNDO', 'INTERNAL'}
|
||||
|
||||
node_index: StringProperty(name='Node Index', default='')
|
||||
in_socket_type: StringProperty(name='In Socket Type', default='NodeSocketShader')
|
||||
out_socket_type: StringProperty(name='Out Socket Type', default='NodeSocketShader')
|
||||
in_socket_type: StringProperty(name='In Socket Type', default='ArmDynamicSocket')
|
||||
out_socket_type: StringProperty(name='Out Socket Type', default='ArmDynamicSocket')
|
||||
in_name_format: StringProperty(name='In Name Format', default='Input {0}')
|
||||
out_name_format: StringProperty(name='Out Name Format', default='Output {0}')
|
||||
in_index_name_offset: IntProperty(name='Index Name Offset', default=0)
|
||||
|
@ -241,8 +318,8 @@ class ArmNodeAddInputOutputButton(bpy.types.Operator):
|
|||
|
||||
# Reset to default again for subsequent calls of this operator
|
||||
self.node_index = ''
|
||||
self.in_socket_type = 'NodeSocketShader'
|
||||
self.out_socket_type = 'NodeSocketShader'
|
||||
self.in_socket_type = 'ArmDynamicSocket'
|
||||
self.out_socket_type = 'ArmDynamicSocket'
|
||||
self.in_name_format = 'Input {0}'
|
||||
self.out_name_format = 'Output {0}'
|
||||
self.in_index_name_offset = 0
|
||||
|
|
267
blender/arm/logicnode/arm_props.py
Normal file
267
blender/arm/logicnode/arm_props.py
Normal file
|
@ -0,0 +1,267 @@
|
|||
"""Custom bpy property creators for logic nodes. Please be aware that
|
||||
the code in this file is usually run once at registration and not for
|
||||
each individual node instance when it is created.
|
||||
|
||||
The functions for creating typed properties wrap the private __haxe_prop
|
||||
function to allow for IDE autocompletion.
|
||||
|
||||
Some default parameters in the signature of functions in this module are
|
||||
mutable (common Python pitfall, be aware of this!), but because they
|
||||
don't get accessed later it doesn't matter here and we keep it this way
|
||||
for parity with the Blender API.
|
||||
"""
|
||||
from typing import Any, Callable, Sequence, Union
|
||||
|
||||
import bpy
|
||||
from bpy.props import *
|
||||
|
||||
|
||||
def __haxe_prop(prop_type: Callable, prop_name: str, *args, **kwargs) -> Any:
|
||||
"""Declares a logic node property as a property that will be
|
||||
used ingame for a logic node."""
|
||||
update_callback: Callable = kwargs.get('update', None)
|
||||
if update_callback is None:
|
||||
def wrapper(self: bpy.types.Node, context: bpy.types.Context):
|
||||
self.on_prop_update(context, prop_name)
|
||||
kwargs['update'] = wrapper
|
||||
else:
|
||||
def wrapper(self: bpy.types.Node, context: bpy.types.Context):
|
||||
update_callback(self, context)
|
||||
self.on_prop_update(context, prop_name)
|
||||
kwargs['update'] = wrapper
|
||||
|
||||
# Tags are not allowed on classes other than bpy.types.ID or
|
||||
# bpy.types.Bone, remove them here to prevent registration errors
|
||||
if 'tags' in kwargs:
|
||||
del kwargs['tags']
|
||||
|
||||
return prop_type(*args, **kwargs)
|
||||
|
||||
|
||||
def HaxeBoolProperty(
|
||||
prop_name: str,
|
||||
*, # force passing further arguments as keywords, see PEP 3102
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default=False,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> 'bpy.types.BoolProperty':
|
||||
"""Declares a new BoolProperty that has a Haxe counterpart with the
|
||||
given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(BoolProperty, **locals())
|
||||
|
||||
|
||||
def HaxeBoolVectorProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default: list = (False, False, False),
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
size: int = 3,
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> list['bpy.types.BoolProperty']:
|
||||
"""Declares a new BoolVectorProperty that has a Haxe counterpart
|
||||
with the given prop_name (Python and Haxe names must be identical
|
||||
for now).
|
||||
"""
|
||||
return __haxe_prop(BoolVectorProperty, **locals())
|
||||
|
||||
|
||||
def HaxeCollectionProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
type=None,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set()
|
||||
) -> 'bpy.types.CollectionProperty':
|
||||
"""Declares a new CollectionProperty that has a Haxe counterpart
|
||||
with the given prop_name (Python and Haxe names must be identical
|
||||
for now).
|
||||
"""
|
||||
return __haxe_prop(CollectionProperty, **locals())
|
||||
|
||||
|
||||
def HaxeEnumProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
items: Sequence,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default: Union[str, set[str]] = None,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> 'bpy.types.EnumProperty':
|
||||
"""Declares a new EnumProperty that has a Haxe counterpart with the
|
||||
given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(EnumProperty, **locals())
|
||||
|
||||
|
||||
def HaxeFloatProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default=0.0,
|
||||
min: float = -3.402823e+38,
|
||||
max: float = 3.402823e+38,
|
||||
soft_min: float = -3.402823e+38,
|
||||
soft_max: float = 3.402823e+38,
|
||||
step: int = 3,
|
||||
precision: int = 2,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
unit: str = 'NONE',
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> 'bpy.types.FloatProperty':
|
||||
"""Declares a new FloatProperty that has a Haxe counterpart with the
|
||||
given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(FloatProperty, **locals())
|
||||
|
||||
|
||||
def HaxeFloatVectorProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default: list = (0.0, 0.0, 0.0),
|
||||
min: float = 'sys.float_info.min',
|
||||
max: float = 'sys.float_info.max',
|
||||
soft_min: float = 'sys.float_info.min',
|
||||
soft_max: float = 'sys.float_info.max',
|
||||
step: int = 3,
|
||||
precision: int = 2,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
unit: str = 'NONE',
|
||||
size: int = 3,
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> list['bpy.types.FloatProperty']:
|
||||
"""Declares a new FloatVectorProperty that has a Haxe counterpart
|
||||
with the given prop_name (Python and Haxe names must be identical
|
||||
for now).
|
||||
"""
|
||||
return __haxe_prop(FloatVectorProperty, **locals())
|
||||
|
||||
|
||||
def HaxeIntProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default=0,
|
||||
min: int = -2**31,
|
||||
max: int = 2**31 - 1,
|
||||
soft_min: int = -2**31,
|
||||
soft_max: int = 2**31 - 1,
|
||||
step: int = 1,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> 'bpy.types.IntProperty':
|
||||
"""Declares a new IntProperty that has a Haxe counterpart with the
|
||||
given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(IntProperty, **locals())
|
||||
|
||||
|
||||
def HaxeIntVectorProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default: list = (0, 0, 0),
|
||||
min: int = -2**31,
|
||||
max: int = 2**31 - 1,
|
||||
soft_min: int = -2**31,
|
||||
soft_max: int = 2**31 - 1,
|
||||
step: int = 1,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
size: int = 3,
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> list['bpy.types.IntProperty']:
|
||||
"""Declares a new IntVectorProperty that has a Haxe counterpart with
|
||||
the given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(IntVectorProperty, **locals())
|
||||
|
||||
|
||||
def HaxePointerProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
type=None,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
poll=None,
|
||||
update=None
|
||||
) -> 'bpy.types.PointerProperty':
|
||||
"""Declares a new PointerProperty that has a Haxe counterpart with
|
||||
the given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(PointerProperty, **locals())
|
||||
|
||||
|
||||
def RemoveHaxeProperty(cls, attr: str):
|
||||
RemoveProperty(cls, attr)
|
||||
|
||||
|
||||
def HaxeStringProperty(
|
||||
prop_name: str,
|
||||
*,
|
||||
name: str = "",
|
||||
description: str = "",
|
||||
default: str = "",
|
||||
maxlen: int = 0,
|
||||
options: set = {'ANIMATABLE'},
|
||||
override: set = set(),
|
||||
tags: set = set(),
|
||||
subtype: str = 'NONE',
|
||||
update=None,
|
||||
get=None,
|
||||
set=None
|
||||
) -> 'bpy.types.StringProperty':
|
||||
"""Declares a new StringProperty that has a Haxe counterpart with
|
||||
the given prop_name (Python and Haxe names must be identical for now).
|
||||
"""
|
||||
return __haxe_prop(StringProperty, **locals())
|
|
@ -1,10 +1,14 @@
|
|||
import bpy
|
||||
from bpy.props import PointerProperty
|
||||
from bpy.props import *
|
||||
from bpy.types import NodeSocket
|
||||
|
||||
import arm.utils
|
||||
|
||||
|
||||
def _on_update_socket(self, context):
|
||||
self.node.on_socket_val_update(context, self)
|
||||
|
||||
|
||||
class ArmCustomSocket(NodeSocket):
|
||||
"""
|
||||
A custom socket that can be used to define more socket types for
|
||||
|
@ -41,7 +45,7 @@ class ArmAnimActionSocket(ArmCustomSocket):
|
|||
arm_socket_type = 'STRING'
|
||||
|
||||
default_value_get: PointerProperty(name='Action', type=bpy.types.Action) # legacy version of the line after this one
|
||||
default_value_raw: PointerProperty(name='Action', type=bpy.types.Action)
|
||||
default_value_raw: PointerProperty(name='Action', type=bpy.types.Action, update=_on_update_socket)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
@ -81,13 +85,114 @@ class ArmArraySocket(ArmCustomSocket):
|
|||
return 0.8, 0.4, 0.0, 1
|
||||
|
||||
|
||||
class ArmBoolSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmBoolSocket'
|
||||
bl_label = 'Boolean Socket'
|
||||
arm_socket_type = 'BOOLEAN'
|
||||
|
||||
default_value_raw: BoolProperty(
|
||||
name='Value',
|
||||
description='Input value used for unconnected socket',
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
draw_socket_layout(self, layout)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.8, 0.651, 0.839, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
class ArmColorSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmColorSocket'
|
||||
bl_label = 'Color Socket'
|
||||
arm_socket_type = 'RGBA'
|
||||
|
||||
default_value_raw: FloatVectorProperty(
|
||||
name='Value',
|
||||
size=4,
|
||||
subtype='COLOR',
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
description='Input value used for unconnected socket',
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
draw_socket_layout(self, layout)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.78, 0.78, 0.161, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
class ArmDynamicSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmDynamicSocket'
|
||||
bl_label = 'Dynamic Socket'
|
||||
arm_socket_type = 'NONE'
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
layout.label(text=self.name)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.388, 0.78, 0.388, 1
|
||||
|
||||
|
||||
class ArmFloatSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmFloatSocket'
|
||||
bl_label = 'Float Socket'
|
||||
arm_socket_type = 'VALUE'
|
||||
|
||||
default_value_raw: FloatProperty(
|
||||
name='Value',
|
||||
description='Input value used for unconnected socket',
|
||||
precision=3,
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
draw_socket_layout(self, layout)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.631, 0.631, 0.631, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
class ArmIntSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmIntSocket'
|
||||
bl_label = 'Integer Socket'
|
||||
arm_socket_type = 'INT'
|
||||
|
||||
default_value_raw: IntProperty(
|
||||
name='Value',
|
||||
description='Input value used for unconnected socket',
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
draw_socket_layout(self, layout)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.059, 0.522, 0.149, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
class ArmObjectSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmNodeSocketObject'
|
||||
bl_label = 'Object Socket'
|
||||
arm_socket_type = 'OBJECT'
|
||||
|
||||
default_value_get: PointerProperty(name='Object', type=bpy.types.Object) # legacy version of the line after this one
|
||||
default_value_raw: PointerProperty(name='Object', type=bpy.types.Object)
|
||||
default_value_raw: PointerProperty(name='Object', type=bpy.types.Object, update=_on_update_socket)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
@ -115,15 +220,82 @@ class ArmObjectSocket(ArmCustomSocket):
|
|||
return 0.15, 0.55, 0.75, 1
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(ArmActionSocket)
|
||||
bpy.utils.register_class(ArmAnimActionSocket)
|
||||
bpy.utils.register_class(ArmArraySocket)
|
||||
bpy.utils.register_class(ArmObjectSocket)
|
||||
class ArmStringSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmStringSocket'
|
||||
bl_label = 'String Socket'
|
||||
arm_socket_type = 'STRING'
|
||||
|
||||
default_value_raw: StringProperty(
|
||||
name='Value',
|
||||
description='Input value used for unconnected socket',
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
draw_socket_layout_split(self, layout)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.439, 0.698, 1, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(ArmObjectSocket)
|
||||
bpy.utils.unregister_class(ArmArraySocket)
|
||||
bpy.utils.unregister_class(ArmAnimActionSocket)
|
||||
bpy.utils.unregister_class(ArmActionSocket)
|
||||
class ArmVectorSocket(ArmCustomSocket):
|
||||
bl_idname = 'ArmVectorSocket'
|
||||
bl_label = 'Vector Socket'
|
||||
arm_socket_type = 'VECTOR'
|
||||
|
||||
default_value_raw: FloatVectorProperty(
|
||||
name='Value',
|
||||
size=3,
|
||||
description='Input value used for unconnected socket',
|
||||
update=_on_update_socket
|
||||
)
|
||||
|
||||
def draw(self, context, layout, node, text):
|
||||
if not self.is_output and not self.is_linked:
|
||||
col = layout.column(align=True)
|
||||
col.prop(self, 'default_value_raw', text='')
|
||||
else:
|
||||
layout.label(text=self.name)
|
||||
|
||||
def draw_color(self, context, node):
|
||||
return 0.388, 0.388, 0.78, 1
|
||||
|
||||
def get_default_value(self):
|
||||
return self.default_value_raw
|
||||
|
||||
|
||||
def draw_socket_layout(socket: bpy.types.NodeSocket, layout: bpy.types.UILayout, prop_name='default_value_raw'):
|
||||
if not socket.is_output and not socket.is_linked:
|
||||
layout.prop(socket, prop_name, text=socket.name)
|
||||
else:
|
||||
layout.label(text=socket.name)
|
||||
|
||||
|
||||
def draw_socket_layout_split(socket: bpy.types.NodeSocket, layout: bpy.types.UILayout, prop_name='default_value_raw'):
|
||||
if not socket.is_output and not socket.is_linked:
|
||||
# Blender layouts use 0.4 splits
|
||||
layout = layout.split(factor=0.4, align=True)
|
||||
|
||||
layout.label(text=socket.name)
|
||||
|
||||
if not socket.is_output and not socket.is_linked:
|
||||
layout.prop(socket, prop_name, text='')
|
||||
|
||||
|
||||
REG_CLASSES = (
|
||||
ArmActionSocket,
|
||||
ArmAnimActionSocket,
|
||||
ArmArraySocket,
|
||||
ArmBoolSocket,
|
||||
ArmColorSocket,
|
||||
ArmDynamicSocket,
|
||||
ArmFloatSocket,
|
||||
ArmIntSocket,
|
||||
ArmObjectSocket,
|
||||
ArmStringSocket,
|
||||
ArmVectorSocket,
|
||||
)
|
||||
register, unregister = bpy.utils.register_classes_factory(REG_CLASSES)
|
||||
|
|
|
@ -10,17 +10,16 @@ class ArrayNode(ArmLogicTreeNode):
|
|||
def __init__(self):
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketShader'
|
||||
op.socket_type = 'ArmDynamicSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -15,13 +15,12 @@ class ArrayAddNode(ArmLogicTreeNode):
|
|||
super(ArrayAddNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayAddNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketBool', 'Modify Original', default_value=True)
|
||||
self.add_input('NodeSocketBool', 'Unique Values')
|
||||
self.add_input('NodeSocketShader', 'Value')
|
||||
self.add_input('ArmBoolSocket', 'Modify Original', default_value=True)
|
||||
self.add_input('ArmBoolSocket', 'Unique Values')
|
||||
self.add_input('ArmDynamicSocket', 'Value')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('ArmNodeSocketArray', 'Array')
|
||||
|
@ -31,6 +30,6 @@ class ArrayAddNode(ArmLogicTreeNode):
|
|||
|
||||
op = row.operator('arm.node_add_input_value', text='Add Input', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketShader'
|
||||
op.socket_type = 'ArmDynamicSocket'
|
||||
op2 = row.operator('arm.node_remove_input_value', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
|
|
@ -11,17 +11,16 @@ class BooleanArrayNode(ArmLogicTreeNode):
|
|||
super(BooleanArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(BooleanArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketBool'
|
||||
op.socket_type = 'ArmBoolSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -11,17 +11,16 @@ class ColorArrayNode(ArmLogicTreeNode):
|
|||
super(ColorArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(ColorArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketColor'
|
||||
op.socket_type = 'ArmColorSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ class ArrayContainsNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Contains'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayContainsNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketShader', 'Value')
|
||||
self.add_input('ArmDynamicSocket', 'Value')
|
||||
|
||||
self.add_output('NodeSocketBool', 'Contains')
|
||||
self.add_output('ArmBoolSocket', 'Contains')
|
||||
|
|
|
@ -11,17 +11,16 @@ class FloatArrayNode(ArmLogicTreeNode):
|
|||
super(FloatArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(FloatArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketFloat'
|
||||
op.socket_type = 'ArmFloatSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ class ArrayGetNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Get'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayGetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketInt', 'Index')
|
||||
self.add_input('ArmIntSocket', 'Index')
|
||||
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
|
|
|
@ -11,17 +11,16 @@ class IntegerArrayNode(ArmLogicTreeNode):
|
|||
super(IntegerArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(IntegerArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array')
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketInt'
|
||||
op.socket_type = 'ArmIntSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ class ArrayLengthNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Length'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayLengthNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
|
|
@ -7,12 +7,11 @@ class ArrayLoopNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Loop'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayLoopNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Loop')
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('NodeSocketInt', 'Index')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
self.add_output('ArmIntSocket', 'Index')
|
||||
self.add_output('ArmNodeSocketAction', 'Done')
|
||||
|
|
|
@ -11,10 +11,9 @@ class ObjectArrayNode(ArmLogicTreeNode):
|
|||
super(ObjectArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(ObjectArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
|
|
@ -8,8 +8,7 @@ class ArrayPopNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Pop'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayPopNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
|
|
|
@ -8,11 +8,10 @@ class ArrayRemoveIndexNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Remove by Index'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayRemoveIndexNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketInt', 'Index')
|
||||
self.add_input('ArmIntSocket', 'Index')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
|
|
|
@ -11,20 +11,19 @@ class ArrayRemoveValueNode(ArmLogicTreeNode):
|
|||
# def __init__(self):
|
||||
# array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayRemoveValueNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketShader', 'Value')
|
||||
self.add_input('ArmDynamicSocket', 'Value')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
|
||||
# def draw_buttons(self, context, layout):
|
||||
# row = layout.row(align=True)
|
||||
|
||||
# op = row.operator('arm.node_add_input_value', text='New', icon='PLUS', emboss=True)
|
||||
# op.node_index = str(id(self))
|
||||
# op.socket_type = 'NodeSocketShader'
|
||||
# op.socket_type = 'ArmDynamicSocket'
|
||||
# op2 = row.operator('arm.node_remove_input_value', text='', icon='X', emboss=True)
|
||||
# op2.node_index = str(id(self))
|
||||
|
|
|
@ -6,11 +6,10 @@ class ArraySetNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Set'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArraySetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketInt', 'Index')
|
||||
self.add_input('NodeSocketShader', 'Value')
|
||||
self.add_input('ArmIntSocket', 'Index')
|
||||
self.add_input('ArmDynamicSocket', 'Value')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -8,8 +8,7 @@ class ArrayShiftNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Shift'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArrayShiftNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
|
||||
self.add_output('NodeSocketShader', 'Value')
|
||||
self.add_output('ArmDynamicSocket', 'Value')
|
||||
|
|
|
@ -8,10 +8,9 @@ class ArraySliceNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Slice'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArraySliceNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketInt', 'Index')
|
||||
self.add_input('NodeSocketInt', 'End')
|
||||
self.add_input('ArmIntSocket', 'Index')
|
||||
self.add_input('ArmIntSocket', 'End')
|
||||
|
||||
self.add_output('ArmNodeSocketArray', 'Array')
|
||||
|
|
|
@ -8,11 +8,10 @@ class ArraySpliceNode(ArmLogicTreeNode):
|
|||
bl_label = 'Array Splice'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ArraySpliceNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketArray', 'Array')
|
||||
self.add_input('NodeSocketInt', 'Index')
|
||||
self.add_input('NodeSocketInt', 'Length')
|
||||
self.add_input('ArmIntSocket', 'Index')
|
||||
self.add_input('ArmIntSocket', 'Length')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -11,17 +11,16 @@ class StringArrayNode(ArmLogicTreeNode):
|
|||
super(StringArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(StringArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketString'
|
||||
op.socket_type = 'ArmStringSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -11,17 +11,16 @@ class VectorArrayNode(ArmLogicTreeNode):
|
|||
super(VectorArrayNode, self).__init__()
|
||||
array_nodes[str(id(self))] = self
|
||||
|
||||
def init(self, context):
|
||||
super(VectorArrayNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketArray', 'Array', is_var=True)
|
||||
self.add_output('NodeSocketInt', 'Length')
|
||||
self.add_output('ArmIntSocket', 'Length')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
row = layout.row(align=True)
|
||||
|
||||
op = row.operator('arm.node_add_input', text='New', icon='PLUS', emboss=True)
|
||||
op.node_index = str(id(self))
|
||||
op.socket_type = 'NodeSocketVector'
|
||||
op.socket_type = 'ArmVectorSocket'
|
||||
op2 = row.operator('arm.node_remove_input', text='', icon='X', emboss=True)
|
||||
op2.node_index = str(id(self))
|
||||
|
||||
|
|
|
@ -8,6 +8,5 @@ class ActiveCameraNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Camera Active'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(ActiveCameraNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketObject', 'Camera')
|
||||
|
|
|
@ -8,8 +8,7 @@ class GetCameraFovNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Camera FOV'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(GetCameraFovNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
|
||||
self.add_output('NodeSocketFloat', 'FOV')
|
||||
self.add_output('ArmFloatSocket', 'FOV')
|
||||
|
|
|
@ -8,8 +8,7 @@ class SetCameraNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Camera Active'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetCameraNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Camera')
|
||||
|
||||
|
|
|
@ -8,10 +8,9 @@ class SetCameraFovNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Camera FOV'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(SetCameraFovNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Camera')
|
||||
self.add_input('NodeSocketFloat', 'FOV', default_value=0.9)
|
||||
self.add_input('ArmFloatSocket', 'FOV', default_value=0.9)
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,8 +6,7 @@ class CanvasGetCheckboxNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Checkbox'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetCheckboxNode, self).init(context)
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('NodeSocketBool', 'Is Checked')
|
||||
self.add_output('ArmBoolSocket', 'Is Checked')
|
||||
|
|
|
@ -6,8 +6,7 @@ class CanvasGetInputTextNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Input Text'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetInputTextNode, self).init(context)
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('NodeSocketString', 'Text')
|
||||
self.add_output('ArmStringSocket', 'Text')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasGetLocationNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Location'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetLocationNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketInt', 'X')
|
||||
self.add_output('NodeSocketInt', 'Y')
|
||||
self.add_output('ArmIntSocket', 'X')
|
||||
self.add_output('ArmIntSocket', 'Y')
|
||||
|
|
|
@ -6,8 +6,7 @@ class CanvasGetPositionNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Position'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetPositionNode, self).init(context)
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('NodeSocketInt', 'Position')
|
||||
self.add_output('ArmIntSocket', 'Position')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasGetPBNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Progress Bar'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetPBNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketInt', 'At')
|
||||
self.add_output('NodeSocketInt', 'Max')
|
||||
self.add_output('ArmIntSocket', 'At')
|
||||
self.add_output('ArmIntSocket', 'Max')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasGetRotationNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Rotation'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetRotationNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketFloat', 'Rad')
|
||||
self.add_output('ArmFloatSocket', 'Rad')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasGetScaleNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Scale'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetScaleNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('NodeSocketInt', 'Height')
|
||||
self.add_output('NodeSocketInt', 'Width')
|
||||
self.add_output('ArmIntSocket', 'Height')
|
||||
self.add_output('ArmIntSocket', 'Width')
|
||||
|
|
|
@ -6,8 +6,7 @@ class CanvasGetSliderNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Slider'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetSliderNode, self).init(context)
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('NodeSocketFloat', 'Float')
|
||||
self.add_output('ArmFloatSocket', 'Float')
|
||||
|
|
|
@ -9,8 +9,7 @@ class CanvasGetVisibleNode(ArmLogicTreeNode):
|
|||
bl_label = 'Get Canvas Visible'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasGetVisibleNode, self).init(context)
|
||||
self.inputs.new('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.inputs.new('ArmStringSocket', 'Element')
|
||||
|
||||
self.outputs.new('NodeSocketBool', 'Is Visible')
|
||||
self.outputs.new('ArmBoolSocket', 'Is Visible')
|
||||
|
|
|
@ -6,24 +6,26 @@ class OnCanvasElementNode(ArmLogicTreeNode):
|
|||
bl_label = 'On Canvas Element'
|
||||
arm_version = 1
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items=[('click', 'Click', 'Listen to mouse clicks'),
|
||||
('hover', 'Hover', 'Listen to mouse hover')],
|
||||
name='Listen to', default='click')
|
||||
property1: EnumProperty(
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
items=[('started', 'Started', 'Started'),
|
||||
('down', 'Down', 'Down'),
|
||||
('released', 'Released', 'Released')],
|
||||
name='Status', default='started')
|
||||
property2: EnumProperty(
|
||||
property2: HaxeEnumProperty(
|
||||
'property2',
|
||||
items=[('left', 'Left', 'Left mouse button'),
|
||||
('middle', 'Middle', 'Middle mouse button'),
|
||||
('right', 'Right', 'Right mouse button')],
|
||||
name='Mouse Button', default='left')
|
||||
|
||||
def init(self, context):
|
||||
super(OnCanvasElementNode, self).init(context)
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetAssetNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Asset'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetAssetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketString', 'Asset')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Asset')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetCheckBoxNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Checkbox'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetCheckBoxNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketBool', 'Check')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmBoolSocket', 'Check')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasSetLocationNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Location'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetLocationNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketFloat', 'X')
|
||||
self.add_input('NodeSocketFloat', 'Y')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmFloatSocket', 'X')
|
||||
self.add_input('ArmFloatSocket', 'Y')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasSetPBNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Progress Bar'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetPBNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketInt', 'At')
|
||||
self.add_input('NodeSocketInt', 'Max')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmIntSocket', 'At')
|
||||
self.add_input('ArmIntSocket', 'Max')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetRotationNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Rotation'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetRotationNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketFloat', 'Rad')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmFloatSocket', 'Rad')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,11 +6,10 @@ class CanvasSetScaleNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Scale'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetScaleNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketInt', 'Height')
|
||||
self.add_input('NodeSocketInt', 'Width')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmIntSocket', 'Height')
|
||||
self.add_input('ArmIntSocket', 'Width')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetSliderNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Slider'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetSliderNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketFloat', 'Float')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmFloatSocket', 'Float')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetTextNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Text'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetTextNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketString', 'Text')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmStringSocket', 'Text')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,13 +6,12 @@ class CanvasSetTextColorNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Text Color'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetTextColorNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketFloat', 'R')
|
||||
self.add_input('NodeSocketFloat', 'G')
|
||||
self.add_input('NodeSocketFloat', 'B')
|
||||
self.add_input('NodeSocketFloat', 'A')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmFloatSocket', 'R')
|
||||
self.add_input('ArmFloatSocket', 'G')
|
||||
self.add_input('ArmFloatSocket', 'B')
|
||||
self.add_input('ArmFloatSocket', 'A')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -6,10 +6,9 @@ class CanvasSetVisibleNode(ArmLogicTreeNode):
|
|||
bl_label = 'Set Canvas Visible'
|
||||
arm_version = 1
|
||||
|
||||
def init(self, context):
|
||||
super(CanvasSetVisibleNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketString', 'Element')
|
||||
self.add_input('NodeSocketBool', 'Visible')
|
||||
self.add_input('ArmStringSocket', 'Element')
|
||||
self.add_input('ArmBoolSocket', 'Visible')
|
||||
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -14,9 +14,8 @@ class GetMouseLockNode(ArmLogicTreeNode):
|
|||
arm_category = 'Input'
|
||||
arm_section = 'mouse'
|
||||
|
||||
def init(self, context):
|
||||
super(GetMouseLockNode, self).init(context)
|
||||
self.outputs.new('NodeSocketBool', 'Is Locked')
|
||||
def arm_init(self, context):
|
||||
self.outputs.new('ArmBoolSocket', 'Is Locked')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
|
|
|
@ -14,9 +14,8 @@ class GetMouseVisibleNode(ArmLogicTreeNode):
|
|||
arm_section = 'mouse'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(GetMouseVisibleNode, self).init(context)
|
||||
self.outputs.new('NodeSocketBool', 'Is Visible')
|
||||
def arm_init(self, context):
|
||||
self.outputs.new('ArmBoolSocket', 'Is Visible')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
|
|
|
@ -11,11 +11,10 @@ class MouseCoordsNode(ArmLogicTreeNode):
|
|||
arm_section = 'mouse'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(MouseCoordsNode, self).init(context)
|
||||
self.add_output('NodeSocketVector', 'Coords')
|
||||
self.add_output('NodeSocketVector', 'Movement')
|
||||
self.add_output('NodeSocketInt', 'Wheel')
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmVectorSocket', 'Coords')
|
||||
self.add_output('ArmVectorSocket', 'Movement')
|
||||
self.add_output('ArmIntSocket', 'Wheel')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
if self.arm_version not in (0, 1):
|
||||
|
|
|
@ -11,7 +11,8 @@ class OnGamepadNode(ArmLogicTreeNode):
|
|||
arm_section = 'gamepad'
|
||||
arm_version = 2
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('Down', 'Down', 'Down'),
|
||||
('Started', 'Started', 'Started'),
|
||||
('Released', 'Released', 'Released')],
|
||||
|
@ -19,7 +20,8 @@ class OnGamepadNode(ArmLogicTreeNode):
|
|||
# ('Moved Right', 'Moved Right', 'Moved Right'),],
|
||||
name='', default='Started')
|
||||
|
||||
property1: EnumProperty(
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
items = [('cross', 'cross / a', 'cross / a'),
|
||||
('circle', 'circle / b', 'circle / b'),
|
||||
('square', 'square / x', 'square / x'),
|
||||
|
@ -40,10 +42,9 @@ class OnGamepadNode(ArmLogicTreeNode):
|
|||
('touchpad', 'touchpad', 'touchpad'),],
|
||||
name='', default='cross')
|
||||
|
||||
def init(self, context):
|
||||
super(OnGamepadNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_input('NodeSocketInt', 'Gamepad')
|
||||
self.add_input('ArmIntSocket', 'Gamepad')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, 'property0')
|
||||
|
|
|
@ -11,13 +11,15 @@ class OnKeyboardNode(ArmLogicTreeNode):
|
|||
arm_section = 'keyboard'
|
||||
arm_version = 2
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('Down', 'Down', 'Down'),
|
||||
('Started', 'Started', 'Started'),
|
||||
('Released', 'Released', 'Released')],
|
||||
name='', default='Started')
|
||||
|
||||
property1: EnumProperty(
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
items = [('a', 'a', 'a'),
|
||||
('b', 'b', 'b'),
|
||||
('c', 'c', 'c'),
|
||||
|
@ -72,8 +74,7 @@ class OnKeyboardNode(ArmLogicTreeNode):
|
|||
('down', 'down', 'down'),],
|
||||
name='', default='space')
|
||||
|
||||
def init(self, context):
|
||||
super(OnKeyboardNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
|
|
|
@ -11,20 +11,21 @@ class OnMouseNode(ArmLogicTreeNode):
|
|||
arm_section = 'mouse'
|
||||
arm_version = 2
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('Down', 'Down', 'Down'),
|
||||
('Started', 'Started', 'Started'),
|
||||
('Released', 'Released', 'Released'),
|
||||
('Moved', 'Moved', 'Moved')],
|
||||
name='', default='Down')
|
||||
property1: EnumProperty(
|
||||
property1: HaxeEnumProperty(
|
||||
'property1',
|
||||
items = [('left', 'left', 'left'),
|
||||
('right', 'right', 'right'),
|
||||
('middle', 'middle', 'middle')],
|
||||
name='', default='left')
|
||||
|
||||
def init(self, context):
|
||||
super(OnMouseNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
|
|
|
@ -11,15 +11,15 @@ class OnSurfaceNode(ArmLogicTreeNode):
|
|||
arm_section = 'surface'
|
||||
arm_version = 2
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('Touched', 'Touched', 'Touched'),
|
||||
('Started', 'Started', 'Started'),
|
||||
('Released', 'Released', 'Released'),
|
||||
('Moved', 'Moved', 'Moved')],
|
||||
name='', default='Touched')
|
||||
|
||||
def init(self, context):
|
||||
super(OnSurfaceNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
|
|
|
@ -11,15 +11,15 @@ class OnVirtualButtonNode(ArmLogicTreeNode):
|
|||
arm_section = 'virtual'
|
||||
arm_version = 2
|
||||
|
||||
property0: EnumProperty(
|
||||
property0: HaxeEnumProperty(
|
||||
'property0',
|
||||
items = [('Down', 'Down', 'Down'),
|
||||
('Started', 'Started', 'Started'),
|
||||
('Released', 'Released', 'Released')],
|
||||
name='', default='Started')
|
||||
property1: StringProperty(name='', default='button')
|
||||
property1: HaxeStringProperty('property1', name='', default='button')
|
||||
|
||||
def init(self, context):
|
||||
super(OnVirtualButtonNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
|
|
|
@ -10,8 +10,7 @@ class PauseActionNode(ArmLogicTreeNode):
|
|||
arm_category = 'Animation'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(PauseActionNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -11,8 +11,7 @@ class PauseTilesheetNode(ArmLogicTreeNode):
|
|||
arm_section = 'tilesheet'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(PauseTilesheetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -10,8 +10,7 @@ class PauseTraitNode(ArmLogicTreeNode):
|
|||
arm_category = 'Trait'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(PauseTraitNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketShader', 'Trait')
|
||||
self.add_input('ArmDynamicSocket', 'Trait')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -10,11 +10,10 @@ class PlayActionNode(ArmLogicTreeNode):
|
|||
arm_category = 'Animation'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(PlayActionNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('ArmNodeSocketAnimAction', 'Action')
|
||||
self.add_input('NodeSocketFloat', 'Blend', default_value=0.2)
|
||||
self.add_input('ArmFloatSocket', 'Blend', default_value=0.2)
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('ArmNodeSocketAction', 'Done')
|
||||
|
|
|
@ -10,8 +10,7 @@ class ResumeActionNode(ArmLogicTreeNode):
|
|||
arm_category = 'Animation'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(ResumeActionNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -10,8 +10,7 @@ class ResumeTilesheetNode(ArmLogicTreeNode):
|
|||
arm_category = 'Animation'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(ResumeTilesheetNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -10,8 +10,7 @@ class ResumeTraitNode(ArmLogicTreeNode):
|
|||
arm_category = 'Trait'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(ResumeTraitNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketShader', 'Trait')
|
||||
self.add_input('ArmDynamicSocket', 'Trait')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -11,12 +11,11 @@ class RotateObjectAroundAxisNode(ArmLogicTreeNode):
|
|||
arm_section = 'rotation'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(RotateObjectAroundAxisNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketVector', 'Axis', default_value=[0, 0, 1])
|
||||
self.add_input('NodeSocketFloat', 'Angle')
|
||||
self.add_input('ArmVectorSocket', 'Axis', default_value=[0, 0, 1])
|
||||
self.add_input('ArmFloatSocket', 'Angle')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
|
|
|
@ -11,9 +11,8 @@ class ScaleObjectNode(ArmLogicTreeNode):
|
|||
arm_section = 'scale'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(ScaleObjectNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketVector', 'Scale')
|
||||
self.add_input('ArmVectorSocket', 'Scale')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
|
|
@ -11,10 +11,9 @@ class SetMouseLockNode(ArmLogicTreeNode):
|
|||
arm_section = 'mouse'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(SetMouseLockNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketBool', 'Lock')
|
||||
self.add_input('ArmBoolSocket', 'Lock')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
|
|
|
@ -11,10 +11,9 @@ class ShowMouseNode(ArmLogicTreeNode):
|
|||
arm_section = 'mouse'
|
||||
arm_version = 2
|
||||
|
||||
def init(self, context):
|
||||
super(ShowMouseNode, self).init(context)
|
||||
def arm_init(self, context):
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('NodeSocketBool', 'Show')
|
||||
self.add_input('ArmBoolSocket', 'Show')
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
|
||||
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue