Upgrading the Math Node

- Dynamically change the number of arguments for the selected operation;
- Exp() operation added.
This commit is contained in:
E1e5en 2020-11-03 09:12:41 +03:00
parent e7fd3cef8a
commit 1352811bcd
2 changed files with 106 additions and 63 deletions

View file

@ -2,7 +2,7 @@ package armory.logicnode;
class MathNode extends LogicNode { class MathNode extends LogicNode {
public var property0: String; public var property0: String; // Operation
public var property1: String; // Clamp public var property1: String; // Clamp
public function new(tree: LogicTree) { public function new(tree: LogicTree) {
@ -10,63 +10,78 @@ class MathNode extends LogicNode {
} }
override function get(from: Int): Dynamic { override function get(from: Int): Dynamic {
var r = 0.0;
var v1: Float = inputs[0].get();
var v2: Float = inputs[1].get();
var f = 0.0;
switch (property0) { switch (property0) {
case "Add": case "Sine":
f = v1 + v2; r = Math.sin(inputs[0].get());
case "Multiply": case "Cosine":
f = v1 * v2; r = Math.cos(inputs[0].get());
case "Sine": case "Abs":
f = Math.sin(v1); r = Math.abs(inputs[0].get());
case "Cosine": case "Tangent":
f = Math.cos(v1); r = Math.tan(inputs[0].get());
case "Max": case "Arcsine":
f = Math.max(v1, v2); r = Math.asin(inputs[0].get());
case "Min": case "Arccosine":
f = Math.min(v1, v2); r = Math.acos(inputs[0].get());
case "Abs": case "Arctangent":
f = Math.abs(v1); r = Math.atan(inputs[0].get());
case "Subtract": case "Logarithm":
f = v1 - v2; r = Math.log(inputs[0].get());
case "Divide": case "Round":
f = v1 / v2; r = Math.round(inputs[0].get());
case "Tangent": case "Floor":
f = Math.tan(v1); r = Math.floor(inputs[0].get());
case "Arcsine": case "Ceil":
f = Math.asin(v1); r = Math.ceil(inputs[0].get());
case "Arccosine": case "Fract":
f = Math.acos(v1); var v = inputs[0].get();
case "Arctangent": r = v - Std.int(v);
f = Math.atan(v1); case "Square Root":
case "Power": r = Math.sqrt(inputs[0].get());
f = Math.pow(v1, v2); case "Exp":
case "Logarithm": r = Math.exp(inputs[0].get());
f = Math.log(v1); case "Max":
case "Round": r = Math.max(inputs[0].get(), inputs[1].get());
f = Math.round(v1); case "Min":
case "Less Than": r = Math.min(inputs[0].get(), inputs[1].get());
f = v1 < v2 ? 1.0 : 0.0; case "Power":
case "Greater Than": r = Math.pow(inputs[0].get(), inputs[1].get());
f = v1 > v2 ? 1.0 : 0.0; case "Less Than":
case "Modulo": r = inputs[0].get() < inputs[1].get() ? 1.0 : 0.0;
f = v1 % v2; case "Greater Than":
case "Arctan2": r = inputs[0].get() > inputs[1].get() ? 1.0 : 0.0;
f = Math.atan2(v1, v2); case "Modulo":
case "Floor": r = inputs[0].get() % inputs[1].get();
f = Math.floor(v1); case "Arctan2":
case "Ceil": r = Math.atan2(inputs[0].get(), inputs[1].get());
f = Math.ceil(v1); case "Add":
case "Fract": for (inp in inputs) r += inp.get();
f = f - Std.int(f); case "Multiply":
case "Square Root": r = inputs[0].get();
f = Math.sqrt(v1); var i = 1;
} while (i < inputs.length) {
r *= inputs[i].get();
i++;
}
case "Subtract":
r = inputs[0].get();
var i = 1;
while (i < inputs.length) {
r -= inputs[i].get();
i++;
}
case "Divide":
r = inputs[0].get();
var i = 1;
while (i < inputs.length) {
r /= inputs[i].get();
i++;
}
}
// Clamp
if (property1 == "true") r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);
if (property1 == "true") f = f < 0.0 ? 0.0 : (f > 1.0 ? 1.0 : f); return r;
return f;
} }
} }

View file

@ -1,19 +1,18 @@
from arm.logicnode.arm_nodes import * from arm.logicnode.arm_nodes import *
class MathNode(ArmLogicTreeNode): class MathNode(ArmLogicTreeNode):
"""Operates values. Some operations uses only the first input.""" """Mathematical operations on values."""
bl_idname = 'LNMathNode' bl_idname = 'LNMathNode'
bl_label = 'Math' bl_label = 'Math'
arm_version = 1 arm_version = 1
property0: EnumProperty( property0: EnumProperty(
items = [('Add', 'Add', 'Add'), items = [('Add', 'Add', 'Add'),
('Multiply', 'Multiply', 'Multiply'), ('Multiply', 'Multiply', 'Multiply'),
('Sine', 'Sine', 'Sine'), ('Sine', 'Sine', 'Sine'),
('Cosine', 'Cosine', 'Cosine'), ('Cosine', 'Cosine', 'Cosine'),
('Max', 'Maximum', 'Max'), ('Max', 'Maximum', 'Max'),
('Min', 'Minimum', 'Min'), ('Min', 'Minimum', 'Min'),
('Abs', 'Absolute', 'Abs'), ('Abs', 'Absolute', 'Abs'),
('Subtract', 'Subtract', 'Subtract'), ('Subtract', 'Subtract', 'Subtract'),
('Divide', 'Divide', 'Divide'), ('Divide', 'Divide', 'Divide'),
('Tangent', 'Tangent', 'Tangent'), ('Tangent', 'Tangent', 'Tangent'),
@ -31,6 +30,7 @@ class MathNode(ArmLogicTreeNode):
('Ceil', 'Ceil', 'Ceil'), ('Ceil', 'Ceil', 'Ceil'),
('Fract', 'Fract', 'Fract'), ('Fract', 'Fract', 'Fract'),
('Square Root', 'Square Root', 'Square Root'), ('Square Root', 'Square Root', 'Square Root'),
('Exp', 'Exponent', 'Exponent'),
], ],
name='', default='Add') name='', default='Add')
@ -40,12 +40,40 @@ class MathNode(ArmLogicTreeNode):
property1_: BoolProperty(name='Clamp', default=False) property1_: BoolProperty(name='Clamp', default=False)
def __init__(self):
array_nodes[str(id(self))] = self
def init(self, context): def init(self, context):
super(MathNode, self).init(context) super(MathNode, self).init(context)
self.add_input('NodeSocketFloat', 'Value 1', default_value=1.0) self.add_input('NodeSocketFloat', 'Value 0', default_value=0.0)
self.add_input('NodeSocketFloat', 'Value 2', default_value=1.0) self.add_input('NodeSocketFloat', 'Value 1', default_value=0.0)
self.add_output('NodeSocketFloat', 'Result') self.add_output('NodeSocketFloat', 'Result')
def draw_buttons(self, context, layout): def draw_buttons(self, context, layout):
layout.prop(self, 'property1_') layout.prop(self, 'property1_')
layout.prop(self, 'property0') layout.prop(self, 'property0')
# Add, Subtract, Multiply, Divide
if (self.property0 == "Add") or (self.property0 == "Subtract") or (self.property0 == "Multiply") or (self.property0 == "Divide"):
while (len(self.inputs) < 2):
self.add_input('NodeSocketFloat', 'Value ' + str(len(self.inputs)))
row = layout.row(align=True)
column = row.column(align=True)
op = column.operator('arm.node_add_input', text='Add Value', icon='PLUS', emboss=True)
op.node_index = str(id(self))
op.socket_type = 'NodeSocketFloat'
op.name_format = 'Value {0}'
column = row.column(align=True)
op = column.operator('arm.node_remove_input', text='', icon='X', emboss=True)
op.node_index = str(id(self))
if len(self.inputs) == 2:
column.enabled = False
# Max, Min, Power, Arctan2, Modulo, Less Than, Greater Than
if (self.property0 == "Max") or (self.property0 == "Min") or (self.property0 == "Power") or (self.property0 == "Arctan2") or (self.property0 == "Modulo") or (self.property0 == "Less Than") or (self.property0 == "Greater Than"):
while (len(self.inputs) > 2):
self.inputs.remove(self.inputs.values()[-1])
while (len(self.inputs) < 2):
self.add_input('NodeSocketFloat', 'Value ' + str(len(self.inputs)))
# Sine, Cosine, Abs, Tangent, Arcsine, Arccosine, Arctangent, Logarithm, Round, Floor, Ceil, Square Root, Fract, Exponent
if (self.property0 == "Sine") or (self.property0 == "Cosine") or (self.property0 == "Abs") or (self.property0 == "Tangent") or (self.property0 == "Arcsine") or (self.property0 == "Arccosine") or (self.property0 == "Arctangent") or (self.property0 == "Logarithm") or (self.property0 == "Round") or (self.property0 == "Floor") or (self.property0 == "Ceil") or (self.property0 == "Square Root") or (self.property0 == "Fract") or (self.property0 == "Exp"):
while (len(self.inputs) > 1):
self.inputs.remove(self.inputs.values()[-1])