Repe [T3DU] Update - 31f26d171bba0355ce2a77031e3aad4c64dbc7e9

This commit is contained in:
2026-09-04 10:46:13 -07:00
parent c915312901
commit 0460b9d587
482 changed files with 27797 additions and 3226 deletions

View File

@ -0,0 +1,12 @@
package leenkx.logicnode;
class ActiveSceneObjectNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
return iron.Scene.active.root.getChild(iron.Scene.active.raw.name);
}
}

View File

@ -3,6 +3,8 @@ package leenkx.logicnode;
import iron.data.SceneFormat.TSceneFormat;
import iron.data.Data;
import iron.object.Object;
import iron.object.MeshObject;
import iron.Scene;
class AddParticleToObjectNode extends LogicNode {
@ -22,22 +24,22 @@ class AddParticleToObjectNode extends LogicNode {
if (objFrom == null || objTo == null) return;
var mobjFrom = cast(objFrom, iron.object.MeshObject);
var mobjFrom = cast(objFrom, MeshObject);
var psys = mobjFrom.particleSystems != null ? mobjFrom.particleSystems[slot] :
mobjFrom.particleOwner != null && mobjFrom.particleOwner.particleSystems != null ? mobjFrom.particleOwner.particleSystems[slot] : null;
if (psys == null) return;
var mobjTo = cast(objTo, iron.object.MeshObject);
mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
var mobjTo = cast(objTo, MeshObject);
mobjTo.setupParticleSystem(Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
mobjTo.render_emitter = inputs[4].get();
iron.Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
if (o != null) {
var c: iron.object.MeshObject = cast o;
var c: MeshObject = cast o;
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
mobjTo.particleChildren.push(c);
c.particleOwner = mobjTo;
@ -55,7 +57,7 @@ class AddParticleToObjectNode extends LogicNode {
var slot: Int = inputs[3].get();
var mobjTo: Object = inputs[4].get();
var mobjTo = cast(mobjTo, iron.object.MeshObject);
var mobjTo = cast(mobjTo, MeshObject);
#if lnx_json
sceneName += ".json";
@ -65,28 +67,34 @@ class AddParticleToObjectNode extends LogicNode {
Data.getSceneRaw(sceneName, (rawScene: TSceneFormat) -> {
for (obj in rawScene.objects) {
if (obj.name == objectName) {
mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
mobjTo.render_emitter = inputs[5].get();
for (obj in rawScene.objects) {
if (obj.name == objectName) {
mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
mobjTo.render_emitter = inputs[5].get();
iron.Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
if (o != null) {
var c: iron.object.MeshObject = cast o;
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
mobjTo.particleChildren.push(c);
c.particleOwner = mobjTo;
c.particleIndex = mobjTo.particleChildren.length - 1;
}
}, true, rawScene);
for (i => ps in rawScene.particle_datas)
if (obj.particle_refs[slot].particle == ps.name){
slot = i;
break;
}
var oslot: Int = mobjTo.particleSystems.length-1;
var opsys = mobjTo.particleSystems[oslot];
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot]);
Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
if (o != null) {
var c: MeshObject = cast o;
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
mobjTo.particleChildren.push(c);
c.particleOwner = mobjTo;
c.particleIndex = mobjTo.particleChildren.length - 1;
}
}, true, rawScene);
break;
var oslot: Int = mobjTo.particleSystems.length-1;
var opsys = mobjTo.particleSystems[oslot];
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot]);
break;
}
}
}
});

View File

@ -111,7 +111,9 @@ class AddPhysicsConstraintNode extends LogicNode {
}
}
}
pivotObject.addTrait(con);
con.name = property0;
pivotObject.addTrait(con);
}
#end
runOutput(0);

View File

@ -0,0 +1,46 @@
package leenkx.logicnode;
import iron.object.Object;
#if lnx_bullet
import leenkx.trait.physics.bullet.PhysicsHook;
#end
class AddPhysicsHookNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var obj: Object = inputs[1].get();
var target: Object = inputs[2].get();
var inputVerts: Dynamic = inputs[3].get();
var flattenedVerts: Array<Float> = [];
if (Std.isOfType(inputVerts, Array)) {
var vArray: Array<Dynamic> = cast inputVerts;
for (v in vArray) {
if (v.x != null) {
flattenedVerts.push(v.x);
flattenedVerts.push(v.y);
flattenedVerts.push(v.z);
}
else if (v[0] != null) {
flattenedVerts.push(v[0]);
flattenedVerts.push(v[1]);
flattenedVerts.push(v[2]);
}
}
}
#if lnx_bullet
var hook = obj.getTrait(PhysicsHook);
if (hook == null) {
hook = new PhysicsHook(target.name, flattenedVerts);
obj.addTrait(hook);
}
#end
runOutput(0);
}
}

View File

@ -20,7 +20,6 @@ class AddRigidBodyNode extends LogicNode {
override function run(from: Int) {
object = inputs[1].get();
if (object == null) return;
#if lnx_physics
@ -70,6 +69,7 @@ class AddRigidBodyNode extends LogicNode {
case "Cylinder": shape = Cylinder;
case "Convex Hull": shape = ConvexHull;
case "Mesh": shape = Mesh;
case "Compound Parent": shape = Compound;
}
rb = new RigidBody(shape, mass, friction, bounciness, group, mask);
@ -77,6 +77,48 @@ class AddRigidBodyNode extends LogicNode {
rb.staticObj = !active;
rb.isTriggerObject(trigger);
if (property0 == "Compound Parent") {
var compoundChildren = [];
for (child in object.children) {
var childRb: RigidBody = child.getTrait(RigidBody);
if (childRb != null) {
var childShape = 0;
switch (@:privateAccess childRb.shape) {
case Box: childShape = 0;
case Sphere: childShape = 1;
case ConvexHull: childShape = 2;
case Mesh: childShape = 3;
case Cone: childShape = 4;
case Cylinder: childShape = 5;
case Capsule: childShape = 6;
default: childShape = 0;
}
childRb.remove();
var m = object.transform.world.clone();
m.getInverse(object.transform.world);
m.multmat(child.transform.world);
var loc = new iron.math.Vec4();
var rot = new iron.math.Quat();
var scl = new iron.math.Vec4();
m.decompose(loc, rot, scl);
compoundChildren.push({
shape: childShape,
posX: loc.x,
posY: loc.y,
posZ: loc.z,
rotX: rot.x,
rotY: rot.y,
rotZ: rot.z,
rotW: rot.w,
dimX: child.transform.dim.x,
dimY: child.transform.dim.y,
dimZ: child.transform.dim.z
});
}
}
@:privateAccess rb.compoundChildren = compoundChildren;
}
if (property1) {
rb.linearDamping = linDamp;
rb.angularDamping = angDamp;

View File

@ -0,0 +1,38 @@
package leenkx.logicnode;
import iron.object.Object;
#if lnx_physics_soft
import leenkx.trait.physics.bullet.SoftBody;
#end
class AddSoftBodyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var obj: Object = inputs[1].get();
if (obj == null) return;
var shape: Int = inputs[2].get(); // 0: Cloth, 1: Volume
var bend: Float = inputs[3].get();
var mass: Float = inputs[4].get();
var margin: Float = inputs[5].get();
var friction: Float = inputs[6].get();
var damping: Float = inputs[7].get();
var pressure: Float = inputs[8].get();
var lStiff: Float = inputs[9].get();
var aStiff: Float = inputs[10].get();
#if lnx_physics_soft
var sb: SoftBody = obj.getTrait(SoftBody);
if (sb == null) {
sb = new SoftBody(shape, bend, mass, margin, friction, damping, lStiff, aStiff, pressure);
obj.addTrait(sb);
}
#end
runOutput(0);
}
}

View File

@ -4,25 +4,38 @@ import iron.object.Object;
class AddTraitNode extends LogicNode {
public var property0: String;
var trait: Dynamic;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var object: Object = inputs[1].get();
var traitName: String = inputs[2].get();
assert(Error, object != null, "Object should not be null");
assert(Error, traitName != null, "Trait name should not be null");
var cname = Type.resolveClass(Main.projectPackage + "." + traitName);
if (cname == null) cname = Type.resolveClass(Main.projectPackage + ".node." + traitName);
assert(Error, cname != null, 'No trait with the name "$traitName" found, make sure that the trait is exported!');
assert(Warning, object.getTrait(cname) == null, 'Object already has the trait "$traitName" applied');
if (property0 == 'TraitName'){
var traitName: String = inputs[2].get();
assert(Error, traitName != null, "Trait name should not be null");
var cname = Type.resolveClass(Main.projectPackage + "." + traitName);
if (cname == null) cname = Type.resolveClass(Main.projectPackage + ".node." + traitName);
assert(Error, cname != null, 'No trait with the name "$traitName" found, make sure that the trait is exported!');
assert(Warning, object.getTrait(cname) == null, 'Object already has the trait "$traitName" applied');
trait = Type.createInstance(cname, []);
} else
trait = inputs[2].get();
var trait = Type.createInstance(cname, []);
object.addTrait(trait);
runOutput(0);
}
override function get(from: Int): Dynamic {
return trait;
}
}

View File

@ -0,0 +1,23 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.CurveObject;
class AlongCurveNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var object: Object = inputs[1].get();
var curve: CurveObject = inputs[2].get();
var splineIdx: Int = inputs[3].get();
var forwardAxis: String = inputs[4].get();
var position: Float = inputs[5].get();
curve.follow(object, position, splineIdx, forwardAxis);
runOutput(0);
}
}

View File

@ -0,0 +1,35 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.Animation;
import iron.object.ObjectAnimation;
class AnimationNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
if (object == null)
return from == 0 ? null : 0;
var animation: Animation = object.animation;
if (animation == null) animation = object.getParentArmature(object.name);
var actions: Array<String> = [];
if (animation.isSkinned)
for(a in animation.armature.actions)
actions.push(a.name);
else
for (a in cast(animation, ObjectAnimation).oactions)
if (a != null)
actions.push(a.objects[0].name);
return from == 0 ? actions : actions.length;
}
}

View File

@ -0,0 +1,29 @@
package leenkx.logicnode;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
#end
import iron.object.Object;
import iron.math.Vec4;
class AroundNavigableLocationNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_navigation
var activeNavMesh: NavMesh = Navigation.active.navMeshes.get(inputs[0].get());
var position: Vec4 = inputs[1].get();
var radius: Float = inputs[2].get();
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
return activeNavMesh.getRandomPointAround(position, radius);
#end
return null;
}
}

View File

@ -12,7 +12,7 @@ class ArrayAddNode extends LogicNode {
override function run(from: Int) {
ar = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
// "Modify Original" == `false` -> Copy the input array
if (!inputs[2].get()) {

View File

@ -2,7 +2,7 @@ package leenkx.logicnode;
class ArrayGetNextNode extends LogicNode {
var i = 0;
var i = -1;
public function new(tree: LogicTree) {
super(tree);
@ -13,12 +13,12 @@ class ArrayGetNextNode extends LogicNode {
if (ar == null) return null;
var value = ar[i];
if (i < ar.length - 1)
i++;
else
i = 0;
var value = ar[i];
return value;

View File

@ -2,7 +2,7 @@ package leenkx.logicnode;
class ArrayGetPreviousNextNode extends LogicNode {
var i = 0;
var i = -1;
public function new(tree: LogicTree) {
super(tree);

View File

@ -13,7 +13,7 @@ class ArrayInsertNode extends LogicNode {
var index: Int = inputs[2].get();
var value: Dynamic = inputs[3].get();
if (ar == null || value == null) return;
assert(Error, ar != null && value != null, 'Array or Value should not be null');
ar.insert(index, value);

View File

@ -11,7 +11,7 @@ class ArrayLoopNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
index = -1;
for (val in ar) {

View File

@ -10,7 +10,7 @@ class ArrayRemoveNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
var i: Int = inputs[2].get();
if (i < 0) i = ar.length + i;

View File

@ -10,7 +10,7 @@ class ArrayRemoveValueNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
var val: Dynamic = inputs[2].get();

View File

@ -8,7 +8,7 @@ class ArrayResizeNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
var len = inputs[2].get();

View File

@ -8,7 +8,7 @@ class ArraySetNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
var i: Int = inputs[2].get();
var value: Dynamic = inputs[3].get();

View File

@ -10,7 +10,7 @@ class ArraySpliceNode extends LogicNode {
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
assert(Error, ar != null, 'Array should not be null');
var i = inputs[2].get();
var len = inputs[3].get();

View File

@ -0,0 +1,62 @@
package leenkx.logicnode;
class AsyncArrayLoopNode extends LogicNode {
var array:Array<Dynamic>;
var index:Int = 0;
var running:Bool = false;
var itemsPerFrame:Int = 1;
public function new(tree:LogicTree) {
super(tree);
}
override function run(from: Int) {
array = inputs[1].get();
itemsPerFrame = inputs[2].get();
index = 0;
if (array == null || array.length == 0) {
runOutput(3);
return;
}
running = true;
tree.notifyOnUpdate(update);
}
function update() {
if (!running) return;
var processed = 0;
while (processed < itemsPerFrame && index < array.length) {
index++;
processed++;
runOutput(0);
if (tree.loopBreak) {
tree.loopBreak = false;
running = false;
tree.removeUpdate(update);
runOutput(2);
return;
}
if (tree.loopContinue) {
tree.loopContinue = false;
continue;
}
}
if (index >= array.length) {
running = false;
tree.removeUpdate(update);
runOutput(3);
}
}
override function get(from: Int): Dynamic {
if (from == 1)
return array[index - 1];
return index - 1;
}
}

View File

@ -0,0 +1,63 @@
package leenkx.logicnode;
class AsyncLoopNode extends LogicNode {
var from:Int;
var to:Int;
var index:Int;
var running:Bool = false;
var itemsPerFrame:Int = 1;
public function new(tree:LogicTree) {
super(tree);
}
override function run(from: Int) {
this.from = inputs[1].get();
this.to = inputs[2].get();
this.itemsPerFrame = inputs[3].get();
index = this.from;
if (this.from >= this.to) {
runOutput(2);
return;
}
running = true;
tree.notifyOnUpdate(update);
}
function update() {
if (!running) return;
var processed = 0;
while (processed < itemsPerFrame && index < to) {
runOutput(0);
index++;
processed++;
if (tree.loopBreak) {
tree.loopBreak = false;
running = false;
tree.removeUpdate(update);
runOutput(2);
return;
}
if (tree.loopContinue) {
tree.loopContinue = false;
continue;
}
}
if (index >= to) {
running = false;
tree.removeUpdate(update);
runOutput(2);
}
}
override function get(from: Int): Dynamic {
return index - 1;
}
}

View File

@ -1,7 +1,5 @@
package leenkx.logicnode;
import iron.object.Object;
class CallFunctionNode extends LogicNode {
var result: Dynamic;
@ -11,8 +9,8 @@ class CallFunctionNode extends LogicNode {
}
override function run(from: Int) {
var object: Dynamic = inputs[1].get();
if (object == null) return;
var trait: Dynamic = inputs[1].get();
if (trait == null){ runOutput(0); return; }
var funName: String = inputs[2].get();
var args: Array<Dynamic> = [];
@ -21,9 +19,9 @@ class CallFunctionNode extends LogicNode {
args.push(inputs[i].get());
}
var func = Reflect.field(object, funName);
var func = Reflect.field(trait, funName);
if (func != null) {
result = Reflect.callMethod(object, func, args);
result = Reflect.callMethod(trait, func, args);
}
runOutput(0);

View File

@ -14,14 +14,16 @@ class CameraGetNode extends LogicNode {
case 3: leenkx.renderpath.Postprocess.camera_uniforms[3];//Camera: Exposure Compensation
case 4: leenkx.renderpath.Postprocess.camera_uniforms[4];//Fisheye Distortion
case 5: leenkx.renderpath.Postprocess.camera_uniforms[5];//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
case 6: leenkx.renderpath.Postprocess.camera_uniforms[6];//DoF Distance
case 7: leenkx.renderpath.Postprocess.camera_uniforms[7];//DoF Focal Length mm
case 8: leenkx.renderpath.Postprocess.camera_uniforms[8];//DoF F-Stop
case 9: leenkx.renderpath.Postprocess.camera_uniforms[9];//Tonemapping Method
case 10: leenkx.renderpath.Postprocess.camera_uniforms[10];//Distort
case 11: leenkx.renderpath.Postprocess.camera_uniforms[11];//Film Grain
case 12: leenkx.renderpath.Postprocess.camera_uniforms[12];//Sharpen
case 13: leenkx.renderpath.Postprocess.camera_uniforms[13];//Vignette
case 6: new iron.math.Vec4(leenkx.renderpath.Postprocess.auto_focus[0], leenkx.renderpath.Postprocess.auto_focus[1], 0, 1); //Auto Focus Value
case 7: leenkx.renderpath.Postprocess.auto_focus[2]; //max blur
case 8: leenkx.renderpath.Postprocess.camera_uniforms[6];//DoF Distance
case 9: leenkx.renderpath.Postprocess.camera_uniforms[7];//DoF Focal Length mm
case 10: leenkx.renderpath.Postprocess.camera_uniforms[8];//DoF F-Stop
case 11: leenkx.renderpath.Postprocess.camera_uniforms[9];//Tonemapping Method
case 12: leenkx.renderpath.Postprocess.camera_uniforms[10];//Distort
case 13: leenkx.renderpath.Postprocess.camera_uniforms[11];//Film Grain
case 14: leenkx.renderpath.Postprocess.camera_uniforms[12];//Sharpen
case 15: leenkx.renderpath.Postprocess.camera_uniforms[13];//Vignette
default: 0.0;
}
}

View File

@ -23,6 +23,11 @@ class CameraSetNode extends LogicNode {
leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[1].get();//Fisheye Distortion
case 'Auto Focus':
leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[1].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
case 'Auto Focus Value':
leenkx.renderpath.Postprocess.auto_focus[0] = inputs[1].get().x;
leenkx.renderpath.Postprocess.auto_focus[1] = inputs[1].get().y;
case 'DoF Max Blur':
leenkx.renderpath.Postprocess.auto_focus[2] = inputs[1].get(); // DoF Max Blur
case 'DoF Distance':
leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[1].get();//DoF Distance
case 'DoF Length':

View File

@ -14,6 +14,7 @@ class CanvasSetSliderNode extends LogicNode {
}
#if lnx_ui
/*
function update() {
if (!canvas.ready) return;
@ -26,7 +27,7 @@ class CanvasSetSliderNode extends LogicNode {
catch (e: Dynamic) {}
runOutput(0);
}
}*/
override function run(from: Int) {
element = inputs[1].get();
@ -34,9 +35,15 @@ class CanvasSetSliderNode extends LogicNode {
canvas = CanvasScript.getActiveCanvas();
canvas.notifyOnReady(() -> {
canvas.getHandle(element).value = value;
runOutput(0);
});
// Ensure canvas is ready
tree.notifyOnUpdate(update);
update();
//tree.notifyOnUpdate(update);
//update();
}
#end
}

View File

@ -4,148 +4,15 @@ import iron.math.Vec4;
class ColorMixNode extends LogicNode {
var SIZE:Int = 38;
var GAMMA:Float = 2.4;
var EPSILON:Float = 0.00000001;
var SPD_C:Array<Float> = [0.96853629, 0.96855103, 0.96859338, 0.96877345, 0.96942204, 0.97143709, 0.97541862, 0.98074186, 0.98580992, 0.98971194, 0.99238027, 0.99409844, 0.995172, 0.99576545, 0.99593552, 0.99564041, 0.99464769, 0.99229579, 0.98638762, 0.96829712, 0.89228016, 0.53740239, 0.15360445, 0.05705719, 0.03126539, 0.02205445, 0.01802271, 0.0161346, 0.01520947, 0.01475977, 0.01454263, 0.01444459, 0.01439897, 0.0143762, 0.01436343, 0.01435687, 0.0143537, 0.01435408];
var SPD_M:Array<Float> = [0.51567122, 0.5401552, 0.62645502, 0.75595012, 0.92826996, 0.97223624, 0.98616174, 0.98955255, 0.98676237, 0.97312575, 0.91944277, 0.32564851, 0.13820628, 0.05015143, 0.02912336, 0.02421691, 0.02660696, 0.03407586, 0.04835936, 0.0001172, 0.00008554, 0.85267882, 0.93188793, 0.94810268, 0.94200977, 0.91478045, 0.87065445, 0.78827548, 0.65738359, 0.59909403, 0.56817268, 0.54031997, 0.52110241, 0.51041094, 0.50526577, 0.5025508, 0.50126452, 0.50083021];
var SPD_Y:Array<Float> = [0.02055257, 0.02059936, 0.02062723, 0.02073387, 0.02114202, 0.02233154, 0.02556857, 0.03330189, 0.05185294, 0.10087639, 0.24000413, 0.53589066, 0.79874659, 0.91186529, 0.95399623, 0.97137099, 0.97939505, 0.98345207, 0.98553736, 0.98648905, 0.98674535, 0.98657555, 0.98611877, 0.98559942, 0.98507063, 0.98460039, 0.98425301, 0.98403909, 0.98388535, 0.98376116, 0.98368246, 0.98365023, 0.98361309, 0.98357259, 0.98353856, 0.98351247, 0.98350101, 0.98350852];
var SPD_R:Array<Float> = [0.03147571, 0.03146636, 0.03140624, 0.03119611, 0.03053888, 0.02856855, 0.02459485, 0.0192952, 0.01423112, 0.01033111, 0.00765876, 0.00593693, 0.00485616, 0.00426186, 0.00409039, 0.00438375, 0.00537525, 0.00772962, 0.0136612, 0.03181352, 0.10791525, 0.46249516, 0.84604333, 0.94275572, 0.96860996, 0.97783966, 0.98187757, 0.98377315, 0.98470202, 0.98515481, 0.98537114, 0.98546685, 0.98550011, 0.98551031, 0.98550741, 0.98551323, 0.98551563, 0.98551547];
var SPD_G:Array<Float> = [0.49108579, 0.46944057, 0.4016578, 0.2449042, 0.0682688, 0.02732883, 0.013606, 0.01000187, 0.01284127, 0.02636635, 0.07058713, 0.70421692, 0.85473994, 0.95081565, 0.9717037, 0.97651888, 0.97429245, 0.97012917, 0.9425863, 0.99989207, 0.99989891, 0.13823139, 0.06968113, 0.05628787, 0.06111561, 0.08987709, 0.13656016, 0.22169624, 0.32176956, 0.36157329, 0.4836192, 0.46488579, 0.47440306, 0.4857699, 0.49267971, 0.49625685, 0.49807754, 0.49889859];
var SPD_B:Array<Float> = [0.97901834, 0.97901649, 0.97901118, 0.97892146, 0.97858555, 0.97743705, 0.97428075, 0.96663223, 0.94822893, 0.89937713, 0.76070164, 0.4642044, 0.20123039, 0.08808402, 0.04592894, 0.02860373, 0.02060067, 0.01656701, 0.01451549, 0.01357964, 0.01331243, 0.01347661, 0.01387181, 0.01435472, 0.01479836, 0.0151525, 0.01540513, 0.01557233, 0.0156571, 0.01571025, 0.01571916, 0.01572133, 0.01572502, 0.01571717, 0.01571905, 0.01571059, 0.01569728, 0.0157002];
var CIE_CMF_X:Array<Float> = [0.00006469, 0.00021941, 0.00112057, 0.00376661, 0.01188055, 0.02328644, 0.03455942, 0.03722379, 0.03241838, 0.02123321, 0.01049099, 0.00329584, 0.00050704, 0.00094867, 0.00627372, 0.01686462, 0.02868965, 0.04267481, 0.05625475, 0.0694704, 0.08305315, 0.0861261, 0.09046614, 0.08500387, 0.07090667, 0.05062889, 0.03547396, 0.02146821, 0.01251646, 0.00680458, 0.00346457, 0.00149761, 0.0007697, 0.00040737, 0.00016901, 0.00009522, 0.00004903, 0.00002];
var CIE_CMF_Y:Array<Float> = [0.00000184, 0.00000621, 0.00003101, 0.00010475, 0.00035364, 0.00095147, 0.00228226, 0.00420733, 0.0066888, 0.0098884, 0.01524945, 0.02141831, 0.03342293, 0.05131001, 0.07040208, 0.08783871, 0.09424905, 0.09795667, 0.09415219, 0.08678102, 0.07885653, 0.0635267, 0.05374142, 0.04264606, 0.03161735, 0.02088521, 0.01386011, 0.00810264, 0.0046301, 0.00249138, 0.0012593, 0.00054165, 0.00027795, 0.00014711, 0.00006103, 0.00003439, 0.00001771, 0.00000722];
var CIE_CMF_Z:Array<Float> = [0.00030502, 0.00103681, 0.00531314, 0.01795439, 0.05707758, 0.11365162, 0.17335873, 0.19620658, 0.18608237, 0.13995048, 0.08917453, 0.04789621, 0.02814563, 0.01613766, 0.0077591, 0.00429615, 0.00200551, 0.00086147, 0.00036904, 0.00019143, 0.00014956, 0.00009231, 0.00006813, 0.00002883, 0.00001577, 0.00000394, 0.00000158, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
var XYZ_RGB:Array<Array<Float>> = [[3.24306333, -1.53837619, -0.49893282], [-0.96896309, 1.87542451, 0.04154303], [0.05568392, -0.20417438, 1.05799454]];
public function linearToConcentration(l1:Float, l2:Float, t:Float):Float {
var t1 = l1 * Math.pow(1 - t, 2);
var t2 = l2 * Math.pow(t, 2);
return t2 / (t1 + t2);
}
public function spectralMix(color1:Array<Int>, color2:Array<Int>, t:Float):Array<Int> {
var lrgb1 = srgbToLinear(color1);
var lrgb2 = srgbToLinear(color2);
var R1 = linearToReflectance(lrgb1);
var R2 = linearToReflectance(lrgb2);
var l1 = dotProduct(R1, CIE_CMF_Y);
var l2 = dotProduct(R2, CIE_CMF_Y);
t = linearToConcentration(l1, l2, t);
var R:Array<Float> = new Array<Float>();
for (i in 0...SIZE) {
var KS = (1 - t) * Math.pow((1 - R1[i]), 2) / (2 * R1[i]) + t * Math.pow((1 - R2[i]), 2) / (2 * R2[i]);
var KM = 1 + KS - Math.sqrt(KS * KS + 2 * KS);
R.push(KM);
}
var xyz = reflectanceToXYZ(R);
return xyzToSrgb(xyz);
}
public function uncompand(x:Float):Float {
return x < 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, GAMMA);
}
public function compand(x:Float):Float {
return x < 0.0031308 ? x * 12.92 : 1.055 * Math.pow(x, 1.0 / GAMMA) - 0.055;
}
public function srgbToLinear(srgb:Array<Int>):Array<Float> {
var r = uncompand(srgb[0] / 255);
var g = uncompand(srgb[1] / 255);
var b = uncompand(srgb[2] / 255);
return [r, g, b];
}
public function linearToSrgb(lrgb:Array<Float>):Array<Int> {
var r = compand(lrgb[0]);
var g = compand(lrgb[1]);
var b = compand(lrgb[2]);
return [Math.round(clamp(r, 0, 1) * 255), Math.round(clamp(g, 0, 1) * 255), Math.round(clamp(b, 0, 1) * 255)];
}
public function reflectanceToXYZ(R:Array<Float>):Array<Float> {
var x = dotProduct(R, CIE_CMF_X);
var y = dotProduct(R, CIE_CMF_Y);
var z = dotProduct(R, CIE_CMF_Z);
return [x, y, z];
}
public function xyzToSrgb(xyz:Array<Float>):Array<Int> {
var r = dotProduct(XYZ_RGB[0], xyz);
var g = dotProduct(XYZ_RGB[1], xyz);
var b = dotProduct(XYZ_RGB[2], xyz);
return linearToSrgb([r, g, b]);
}
public function spectralUpsampling(lrgb:Array<Float>):Array<Float> {
var w = Math.min(Math.min(lrgb[0], lrgb[1]), lrgb[2]);
var lrgbNew = [lrgb[0] - w, lrgb[1] - w, lrgb[2] - w];
var c = Math.min(lrgbNew[1], lrgbNew[2]);
var m = Math.min(lrgbNew[0], lrgbNew[2]);
var y = Math.min(lrgbNew[0], lrgbNew[1]);
var r = Math.max(0, Math.min(lrgbNew[0] - lrgbNew[2], lrgbNew[0] - lrgbNew[1]));
var g = Math.max(0, Math.min(lrgbNew[1] - lrgbNew[2], lrgbNew[1] - lrgbNew[0]));
var b = Math.max(0, Math.min(lrgbNew[2] - lrgbNew[1], lrgbNew[2] - lrgbNew[0]));
return [w, c, m, y, r, g, b];
}
public function linearToReflectance(lrgb:Array<Float>):Array<Float> {
var weights = spectralUpsampling(lrgb);
var R:Array<Float> = new Array<Float>();
for (i in 0...SIZE) {
R[i] = Math.max(EPSILON,
weights[0]
+ weights[1] * SPD_C[i]
+ weights[2] * SPD_M[i]
+ weights[3] * SPD_Y[i]
+ weights[4] * SPD_R[i]
+ weights[5] * SPD_G[i]
+ weights[6] * SPD_B[i]
);
}
return R;
}
public function dotProduct(a:Array<Float>, b:Array<Float>):Float {
var sum:Float = 0;
for (i in 0...a.length) {
sum += a[i] * b[i];
}
return sum;
}
public function clamp(value:Float, minValue:Float, maxValue:Float):Float {
return Math.min(Math.max(value, minValue), maxValue);
}
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var Color1:Vec4 = inputs[0].get();
var Color2:Vec4 = inputs[1].get();
var mix:Float = inputs[2].get();
mix = Math.min(Math.max(mix, 0), 1);
var col1 = [Std.int(Color1.x*255), Std.int(Color1.y*255), Std.int(Color1.z*255)];
var col2 = [Std.int(Color2.x*255), Std.int(Color2.y*255), Std.int(Color2.z*255)];
var ColorMix = spectralMix(col1, col2, mix);
return new Vec4(ColorMix[0]/255, ColorMix[1]/255, ColorMix[2]/255, (Color1.w+Color2.w)/2);
var c1: Vec4 = inputs[0].get();
var c2: Vec4 = inputs[1].get();
var factor: Float = inputs[2].get();
return leenkx.trait.internal.Spectral.mix([c1, c2], [1.0 - factor, factor]);
}
}

View File

@ -0,0 +1,26 @@
package leenkx.logicnode;
import iron.math.Vec4;
import leenkx.trait.internal.Spectral;
class ColorsMixNode extends LogicNode {
var result = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var colors: Array<Vec4> = inputs[0].get();
var factors: Array<Float> = inputs[1].get();
if (colors == null || factors == null || colors.length == 0 || factors.length == 0) {
return result;
}
result.setFrom(Spectral.mix(colors, factors));
return result;
}
}

View File

@ -0,0 +1,73 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.MeshObject;
import leenkx.object.BreakerExtension;
import iron.math.Vec4;
class ConvexBreakNode extends LogicNode {
public var property0: String;
var objects: Array<Object>;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
objects = [];
var object: Object = inputs[1].get();
var breaker: ConvexBreaker = new ConvexBreaker(0.1);
@:privateAccess breaker.scaleUV = inputs[3].get();
@:privateAccess breaker.flatShading = inputs[4].get();
breaker.initBreakableObject(cast object, 0, 0, new Vec4(), new Vec4(), true);
var debris: Array<MeshObject> = [];
if (property0 == 'Plane')
debris = breaker.subdivideByPlane(cast object, inputs[3].get(), inputs[2].get());
else
debris = breaker.subdivideByImpact(cast object, inputs[2].get(), inputs[3].get(), 1, 1);
for (o in debris) {
var obj: Object = cast o;
obj.name = o.data.raw.name;
var dims = new kha.arrays.Float32Array(3);
dims[0] = o.data.geom.aabb.x;
dims[1] = o.data.geom.aabb.y;
dims[2] = o.data.geom.aabb.z;
obj.raw = cast {
type: "mesh_object",
name: obj.name,
data_ref: obj.name,
dimensions: dims
};
obj.addTrait(new leenkx.trait.internal.UniformsManager());
var ud = breaker.userDataMap.get(cast o);
if (ud == null) continue;
objects.push(obj);
}
if (objects.length > 1){
for (obj in objects)
obj.setParent(iron.Scene.active.root);
object.remove();
runOutput(1);
}
else
runOutput(2);
runOutput(0);
}
override function get(from: Int): Dynamic {
return objects;
}
}

View File

@ -1,7 +1,6 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
import leenkx.system.Event;
class CreateMapNode extends LogicNode {

View File

@ -2,6 +2,8 @@ package leenkx.logicnode;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
import leenkx.trait.NavCrowd;
#end
import iron.object.Object;
@ -9,24 +11,30 @@ import iron.math.Vec4;
class CrowdGoToLocationNode extends LogicNode {
var object: Object;
var location: Vec4;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
object = inputs[1].get();
location = inputs[2].get();
var navMeshId: String = inputs[1].get();
var object: Object = inputs[2].get();
var location: Vec4 = inputs[3].get();
var maxSpeed: Float = inputs[4].get();
var maxAcceleration: Float = inputs[5].get();
var turnSpeed: Float = inputs[6].get();
assert(Error, object != null, "The object input not be null");
assert(Error, location != null, "The location to navigate to must not be null");
#if lnx_navigation
assert(Error, Navigation.active.navMeshes.length > 0, "No Navigation Mesh Present");
var crowdAgent: leenkx.trait.NavCrowd = object.getTrait(leenkx.trait.NavCrowd);
var activeNavMesh: NavMesh = Navigation.active.navMeshes.get(navMeshId);
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
var crowdAgent: NavCrowd = object.getTrait(NavCrowd);
assert(Error, crowdAgent != null, "Object does not have a NavCrowd trait");
crowdAgent.crowdAgentSetMaxSpeed(maxSpeed);
crowdAgent.crowdAgentSetMaxAcceleration(maxAcceleration);
crowdAgent.turnSpeed = turnSpeed;
crowdAgent.crowdAgentGoto(location);
#end
runOutput(0);

View File

@ -0,0 +1,33 @@
package leenkx.logicnode;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
import leenkx.trait.NavCrowd;
#end
import iron.object.Object;
import iron.math.Vec4;
class CrowdSetLocationNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var navMeshId: String = inputs[1].get();
var object: Object = inputs[2].get();
var location: Vec4 = inputs[3].get();
#if lnx_navigation
var activeNavMesh: NavMesh = Navigation.active.navMeshes.get(navMeshId);
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
var crowdAgent: NavCrowd = object.getTrait(NavCrowd);
assert(Error, crowdAgent != null, "Object does not have a NavCrowd trait");
crowdAgent.crowdAgentTeleport(location);
#end
runOutput(0);
}
}

View File

@ -0,0 +1,33 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.MeshObject;
class CurveGuideNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_cpu_particles
var object: Object = inputs[1].get();
var slot: Int = inputs[2].get();
if (object == null){ runOutput(0); return; }
var mo: MeshObject = cast object;
var psys = mo.particleSystems != null ? mo.particleSystems[slot] : null;
if (psys == null){ runOutput(0); return; }
psys.curveGuides = inputs[3].get();
psys.curveGuideStrength = inputs[4].get();
psys.curveGuideSpeed = inputs[5].get();
#end
runOutput(0);
}
}

View File

@ -0,0 +1,27 @@
package leenkx.logicnode;
import iron.object.CurveObject;
import iron.object.MeshObject;
import iron.data.MeshData;
class DeformCurveNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var mo: MeshObject = inputs[1].get();
var curve: CurveObject = inputs[2].get();
var mData: MeshData = curve.generateDeformedMesh(mo.data, inputs[3].get(), inputs[4].get(), 1, inputs[5].get(), inputs[6].get());
if (mData != null){
mo.setData(mData);
mo.transform.scale.set(1, 1, 1);
mo.transform.buildMatrix();
}
runOutput(0);
}
}

View File

@ -8,11 +8,9 @@ import iron.object.CameraObject;
import leenkx.renderpath.RenderPathCreator;
class DrawCameraNode extends LogicNode {
static inline var numStaticInputs = 2;
var cameras: Array<CameraObject>;
var renderTargets: Array<kha.Image>;
var positions: Array<Vec2>;
var camera: CameraObject;
var renderTarget: kha.Image;
var position: Vec2 = new Vec2();
public function new(tree: LogicTree) {
super(tree);
@ -21,39 +19,18 @@ class DrawCameraNode extends LogicNode {
override function run(from: Int) {
switch (from) {
case 0: // Start
if (cameras == null) {
final numDynamicInputs = inputs.length - numStaticInputs;
final numCams = Std.int(numDynamicInputs / 5);
camera = inputs[2].get();
position.set(
inputs[3].get(),
inputs[4].get()
);
// Preallocate
cameras = [];
cameras.resize(numCams);
positions = [];
positions.resize(numCams);
for (i in 0...positions.length) {
positions[i] = new Vec2();
}
renderTargets = [];
renderTargets.resize(numCams);
}
for (i in 0...cameras.length) {
cameras[i] = inputs[numStaticInputs + i * 5].get();
positions[i].set(
inputs[numStaticInputs + i * 5 + 1].get(),
inputs[numStaticInputs + i * 5 + 2].get()
);
// TODO: implement proper rendertarget cache/pool
renderTargets[i] = kha.Image.createRenderTarget(
inputs[numStaticInputs + i * 5 + 3].get(), // w
inputs[numStaticInputs + i * 5 + 4].get(), // h
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil
);
}
renderTarget = kha.Image.createRenderTarget(
inputs[5].get(), // w
inputs[6].get(), // h
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil
);
tree.notifyOnRender(render);
tree.notifyOnRender2D(render2D);
@ -67,47 +44,45 @@ class DrawCameraNode extends LogicNode {
}
function render(g:kha.graphics4.Graphics) {
if (inputs[7].get()) return;
final rpPaused = RenderPath.active.paused;
RenderPath.active.paused = false;
final sceneCam = iron.Scene.active.camera;
for (i in 0...cameras.length) {
final cam = cameras[i];
final cam = camera;
final oldRT = cam.renderTarget;
cam.renderTarget = renderTargets[i];
final oldRT = cam.renderTarget;
cam.renderTarget = renderTarget;
iron.Scene.active.camera = cam;
cam.renderFrame(g);
iron.Scene.active.camera = cam;
cam.renderFrame(g);
cam.renderTarget = oldRT;
}
cam.renderTarget = oldRT;
iron.Scene.active.camera = sceneCam;
RenderPath.active.paused = rpPaused;
}
function render2D(g: kha.graphics2.Graphics) {
for(i in 0...cameras.length) {
final rt = renderTargets[i];
if (inputs[7].get()) return;
final rt = renderTarget;
positions[i].set(
inputs[numStaticInputs + i * 5 + 1].get(),
inputs[numStaticInputs + i * 5 + 2].get()
);
position.set(
inputs[3].get(),
inputs[4].get()
);
final posX = positions[i].x;
final posY = positions[i].y;
final posX = position.x;
final posY = position.y;
g.color = 0xff000000;
g.fillRect(posX, posY, rt.width, rt.height);
g.color = 0xffffffff;
if (kha.Image.renderTargetsInvertedY())
g.drawScaledImage(rt, posX, posY+rt.height, rt.width, -rt.height);
else
g.drawScaledImage(rt, posX, posY, rt.width, rt.height);
}
g.color = 0xff000000;
g.fillRect(posX, posY, rt.width, rt.height);
g.color = 0xffffffff;
if (kha.Image.renderTargetsInvertedY())
g.drawScaledImage(rt, posX, posY+rt.height, rt.width, -rt.height);
else
g.drawScaledImage(rt, posX, posY, rt.width, rt.height);
}
}

View File

@ -0,0 +1,129 @@
package leenkx.logicnode;
import iron.math.Vec4;
import kha.Image;
import kha.Color;
import leenkx.renderpath.RenderToTexture;
import iron.format.gif.Reader;
import iron.format.gif.Data;
import iron.format.gif.Tools;
import haxe.io.Bytes;
import haxe.io.BytesInput;
import leenkx.system.Event;
class DrawGifNode extends LogicNode {
var data:Data = null;
var frames:Int = 0;
var img: Array<Image> = [];
var lastImgName = "";
var duration = 0.0;
var index = 0;
var i = 0;
public function new(tree: LogicTree) {
super(tree);
Event.add('load', function() {
var extractedBytes:Bytes = Tools.extractFullRGBA(data, i);
img.push(kha.Image.fromBytes(extractedBytes, data.logicalScreenDescriptor.width, data.logicalScreenDescriptor.height, kha.graphics4.TextureFormat.RGBA32));
});
tree.notifyOnRemove(onRemove);
}
function onRemove() {
Event.remove('load');
}
override function run(from: Int) {
if (from == 0){
if (data == null){
runOutput(0);
return;
}
RenderToTexture.ensure2DContext("DrawGifNode");
final colorVec: Vec4 = inputs[3].get();
final anchorH: Int = inputs[4].get();
final anchorV: Int = inputs[5].get();
final x: Float = inputs[6].get();
final y: Float = inputs[7].get();
final width: Float = inputs[8].get();
final height: Float = inputs[9].get();
final angle: Float = inputs[10].get();
var sindex: Int = inputs[11].get();
var eindex: Int = inputs[12].get();
final fdur: Float = inputs[13].get();
final loop: Bool = inputs[14].get();
final drawx = x - 0.5 * width * anchorH;
final drawy = y - 0.5 * height * anchorV;
if(eindex == -1 || eindex > frames)
eindex = frames;
if(sindex < 0 || sindex > frames)
sindex = 0;
if (index < sindex || index > eindex)
index = sindex;
duration += iron.system.Time.delta;
if (duration >= fdur){
if (index < eindex)
index += 1;
else
if (loop) index = sindex;
duration = 0;
if (i < eindex){
++i;
Event.send('load');
}
}
if (img.length > (index - sindex)){
RenderToTexture.g.rotate(angle, x, y);
RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
RenderToTexture.g.drawScaledImage(img[index-sindex], drawx, drawy, width, height);
RenderToTexture.g.rotate(-angle, x, y);
}
runOutput(0);
}
else{
final imgName: String = inputs[2].get();
if (imgName != lastImgName) {
lastImgName = imgName;
img = [];
i = inputs[11].get();
index = i;
iron.data.Data.getBlob(imgName, (blob: kha.Blob) -> {
var bytes: Bytes = blob.toBytes();
var input: BytesInput = new BytesInput(bytes);
data = new Reader(input).read();
frames = Tools.framesCount(data);
if (i > frames) return;
var extractedBytes:Bytes = Tools.extractFullRGBA(data, i);
img.push(kha.Image.fromBytes(extractedBytes, data.logicalScreenDescriptor.width, data.logicalScreenDescriptor.height, kha.graphics4.TextureFormat.RGBA32));
++i;
Event.send('load');
});
}
}
}
override function get(from: Int): Dynamic {
if (from == 1)
return frames;
else
return index;
}
}

View File

@ -1,12 +1,15 @@
package leenkx.logicnode;
import iron.math.Vec4;
import iron.RenderPath;
import kha.Image;
import kha.Color;
import leenkx.renderpath.RenderToTexture;
class DrawImageRenderNode extends LogicNode {
var img: Image;
var img2D: Image;
var initialized: Bool = false;
public function new(tree: LogicTree) {
super(tree);
@ -14,8 +17,21 @@ class DrawImageRenderNode extends LogicNode {
override function run(from: Int) {
if (from == 1)
if (from == 1){
if (inputs[16].get()){
if (initialized) return;
initialized = true;
}
img = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
if (inputs[15].get() || kha.Image.renderTargetsInvertedY())
img2D = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
tree.notifyOnRender(render);
}
else {
RenderToTexture.ensure2DContext("DrawImageRenderNode");
@ -38,12 +54,14 @@ class DrawImageRenderNode extends LogicNode {
RenderToTexture.g.rotate(angle, x, y);
if (img != null){
RenderToTexture.g.color = 0xff000000;
RenderToTexture.g.fillRect(drawx, drawy, width, height);
RenderToTexture.g.color = RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
RenderToTexture.g.color = 0xff000000;
RenderToTexture.g.fillRect(drawx, drawy, width, height);
RenderToTexture.g.color = RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
if ((inputs[15].get() || kha.Image.renderTargetsInvertedY()) && img2D != null)
RenderToTexture.g.drawScaledSubImage(img2D, sx, sy, swidth, sheight, drawx, drawy, width, height);
else if(img != null)
RenderToTexture.g.drawScaledSubImage(img, sx, sy, swidth, sheight, drawx, drawy, width, height);
}
RenderToTexture.g.rotate(-angle, x, y);
@ -54,13 +72,11 @@ class DrawImageRenderNode extends LogicNode {
}
function render(g: kha.graphics4.Graphics) {
final rpPaused = RenderPath.active.paused;
RenderPath.active.paused = false;
var camera = inputs[2].get();
img = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
final sceneCam = iron.Scene.active.camera;
final oldRT = camera.renderTarget;
@ -69,38 +85,30 @@ class DrawImageRenderNode extends LogicNode {
camera.renderFrame(g);
img = camera.renderTarget;
if (inputs[15].get() || kha.Image.renderTargetsInvertedY()) {
img = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(),
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
img2D.g2.begin(true, Color.Transparent);
img2D.g2.color = Color.White;
img.g2.begin(true, Color.Transparent);
if (kha.Image.renderTargetsInvertedY())
img2D.g2.drawScaledImage(camera.renderTarget, 0, iron.App.h(), iron.App.w(), -iron.App.h());
else
img2D.g2.drawImage(camera.renderTarget, 0, 0);
img.g2.color = Color.White;
if (kha.Image.renderTargetsInvertedY()) {
img.g2.drawScaledImage(camera.renderTarget, 0, iron.App.h(), iron.App.w(), -iron.App.h());
} else {
img.g2.drawImage(camera.renderTarget, 0, 0);
}
if (inputs[15].get()) {
for (f in @:privateAccess iron.App.traitRenders2D) {
f(img.g2);
}
}
img.g2.end();
if (inputs[15].get())
for (f in @:privateAccess iron.App.traitRenders2D)
f(img2D.g2);
img2D.g2.end();
}
camera.renderTarget = oldRT;
iron.Scene.active.camera = sceneCam;
tree.removeRender(render);
RenderPath.active.paused = rpPaused;
if (!inputs[16].get())
tree.removeRender(render);
}

View File

@ -16,8 +16,8 @@ class DrawRoundedRectNode extends LogicNode {
super(tree);
}
#if lnx_ui
override function run(from: Int) {
#if lnx_ui
RenderToTexture.ensure2DContext("DrawPolygonNode");
final anchorH: Int = inputs[4].get();
@ -61,8 +61,6 @@ class DrawRoundedRectNode extends LogicNode {
} else {
RenderToTexture.g.drawPolygon(0, 0, vertices, inputs[3].get());
}
#end
RenderToTexture.g.rotate(-angle, x, y);
runOutput(0);
}
@ -115,4 +113,5 @@ class DrawRoundedRectNode extends LogicNode {
return vertices;
}
#end
}

View File

@ -3,9 +3,13 @@ package leenkx.logicnode;
import kha.Font;
import kha.Color;
import leenkx.renderpath.RenderToTexture;
import kha.graphics2.VerTextAlignment;
import kha.graphics2.HorTextAlignment;
#if lnx_ui
import leenkx.ui.Canvas;
using zui.GraphicsExtension;
#end
class DrawStringNode extends LogicNode {
@ -13,13 +17,20 @@ class DrawStringNode extends LogicNode {
var lastFontName = "";
var string:String;
public var property1: String;
public var property2: String;
public function new(tree: LogicTree) {
super(tree);
}
#if lnx_ui
override function run(from: Int) {
RenderToTexture.ensure2DContext("DrawStringNode");
var horA = TextLeft;
var verA = TextTop;
string = Std.string(inputs[1].get());
var angle: Float = inputs[7].get();
@ -45,6 +56,18 @@ class DrawStringNode extends LogicNode {
return;
}
switch(property1){
case 'TextLeft': horA = TextLeft;
case 'TextCenter': horA = TextCenter;
case 'TextRight': horA = TextRight;
}
switch(property2){
case 'TextTop': verA = TextTop;
case 'TextMiddle': verA = TextMiddle;
case 'TextBottom': verA = TextBottom;
}
RenderToTexture.g.rotate(angle, inputs[5].get(), inputs[6].get());
final colorVec = inputs[4].get();
@ -53,7 +76,7 @@ class DrawStringNode extends LogicNode {
RenderToTexture.g.fontSize = inputs[3].get();
RenderToTexture.g.font = font;
RenderToTexture.g.drawString(string, inputs[5].get(), inputs[6].get());
RenderToTexture.g.drawAlignedString(string, inputs[5].get(), inputs[6].get(), horA, verA);
RenderToTexture.g.rotate(-angle, inputs[5].get(), inputs[6].get());
@ -65,4 +88,5 @@ class DrawStringNode extends LogicNode {
return from == 1 ? RenderToTexture.g.font.width(RenderToTexture.g.fontSize, string) : RenderToTexture.g.font.height(RenderToTexture.g.fontSize);
}
#end
}

View File

@ -0,0 +1,47 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.CurveObject;
import iron.system.Time;
class FollowCurveNode extends LogicNode {
var progress: Float = -1;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var cycle: Bool = false;
var object: Object = inputs[1].get();
var curve: CurveObject = inputs[2].get();
var splineIdx: Int = inputs[3].get();
if (progress == -1) progress = inputs[8].get();
var len = curve.getLength(splineIdx);
var speed = inputs[5].get();
var currentDist = progress * len;
currentDist += (speed * Time.delta * (inputs[6].get() ? 1.0 : -1.0));
if (inputs[7].get()){
if (currentDist > len){ currentDist -= len; cycle = true; }
else if (currentDist < 0){ currentDist += len; cycle = true; }
}
progress = (len > 0) ? currentDist / len : 0.0;
if (cycle)
runOutput(1);
else{
curve.follow(object, progress, splineIdx, inputs[4].get());
runOutput(0);
}
}
override function get(from: Int): Dynamic {
return progress;
}
}

View File

@ -0,0 +1,57 @@
package leenkx.logicnode;
class FormatNumberNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var number: Float = inputs[0].get();
var thousandsSeparator: String = inputs[1].get();
var decimalSeparator: String = inputs[2].get();
var includeSymbol: Bool = inputs[3].get();
var s = Std.string(number);
var isNegative = s.charAt(0) == "-";
if (isNegative) s = s.substring(1);
var parts = s.split(".");
var integerPart = parts[0];
var decimalPart = (parts.length > 1) ? parts[1] : "";
var len = integerPart.length;
var formattedInteger = "";
if (len <= 3) {
formattedInteger = integerPart;
} else {
var firstGroupLen = len % 3;
if (firstGroupLen == 0) firstGroupLen = 3;
formattedInteger += integerPart.substring(0, firstGroupLen);
var i = firstGroupLen;
while (i < len) {
formattedInteger += thousandsSeparator + integerPart.substring(i, i + 3);
i += 3;
}
}
var finalNumber = formattedInteger;
if (decimalPart != "") {
finalNumber += decimalSeparator + decimalPart;
}
var result = "";
var sign = isNegative ? "-" : "";
if (includeSymbol) {
result = sign + "$" + finalNumber;
} else {
result = sign + finalNumber;
}
return result;
}
}

View File

@ -0,0 +1,32 @@
package leenkx.logicnode;
class FormatTimeNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var time: Float = inputs[0].get();
var format: String = inputs[1].get();
var totalSeconds = Math.floor(time);
var milliseconds = Math.floor((time - totalSeconds) * 1000);
var centiseconds = Math.floor(milliseconds / 10);
var h = Math.floor(totalSeconds / 3600);
var m = Math.floor((totalSeconds % 3600) / 60);
var s = totalSeconds % 60;
var result = format;
result = StringTools.replace(result, "HH", (h < 10 ? "0" : "") + h);
result = StringTools.replace(result, "MM", (m < 10 ? "0" : "") + m);
result = StringTools.replace(result, "SS", (s < 10 ? "0" : "") + s);
result = StringTools.replace(result, "MS", (centiseconds < 10 ? "0" : "") + centiseconds);
result = StringTools.replace(result, "H", "" + h);
result = StringTools.replace(result, "M", "" + m);
result = StringTools.replace(result, "S", "" + s);
return result;
}
}

View File

@ -2,24 +2,32 @@ package leenkx.logicnode;
import iron.object.Object;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavAgent;
#end
class GetAgentDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Float {
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
assert(Error, object != null, "The object to naviagte should not be null");
#if lnx_navigation
var agent: leenkx.trait.NavAgent = object.getTrait(leenkx.trait.NavAgent);
assert(Error, agent != null, "The object does not have NavAgent Trait");
if(from == 0) return agent.speed;
else return agent.turnDuration;
#else
return null;
#end
#if lnx_navigation
var agent: NavAgent = object.getTrait(NavAgent);
if (agent == null) return null;
return switch(from){
case 0: agent.navMeshId;
case 1: agent.speed;
case 2: agent.turnDuration;
case 3: @:privateAccess agent.path;
default: null;
}
#else
return null;
#end
}
}

View File

@ -0,0 +1,27 @@
package leenkx.logicnode;
import iron.object.LightObject;
class GetAreaLightDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var light: LightObject = inputs[0].get();
if (light == null) return null;
#if lnx_ltc
if (light.data.raw.type == "area")
if (from == 0)
return light.data.raw.size;
else
return light.data.raw.size_y;
#end
return null;
}
}

View File

@ -0,0 +1,12 @@
package leenkx.logicnode;
class GetAssetsNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
return leenkx.system.Starter.assets;
}
}

View File

@ -1,10 +1,18 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.MeshObject;
import iron.object.CameraObject;
import iron.object.LightObject;
import iron.object.SpeakerObject;
import iron.object.DecalObject;
import iron.object.ProbeObject;
import iron.object.CurveObject;
class GetChildNode extends LogicNode {
public var property0: String;
public var property1: String;
public function new(tree: LogicTree) {
super(tree);
@ -12,22 +20,31 @@ class GetChildNode extends LogicNode {
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var childName: String = inputs[1].get();
if (object == null) return null;
if (object == null || childName == null) return null;
if (property0 != "By Type") {
var childName: String = inputs[1].get();
if (childName == null) return null;
switch (property0) {
case "By Name":
return object.getChild(childName);
case "Contains":
return contains(object, childName);
case "Starts With":
return startsWith(object, childName);
case "Ends With":
return endsWith(object, childName);
return switch (property0) {
case "By Name": object.getChild(childName);
case "Contains": contains(object, childName);
case "Starts With": startsWith(object, childName);
case "Ends With": endsWith(object, childName);
default: null;
}
}
return null;
return switch (property1) {
case "MeshObject": object.getChildOfType(MeshObject);
case "CameraObject": object.getChildOfType(CameraObject);
case "LightObject": object.getChildOfType(LightObject);
case "SpeakerObject": object.getChildOfType(SpeakerObject);
case "DecalObject": object.getChildOfType(DecalObject);
case "ProbeObject": object.getChildOfType(ProbeObject);
case "CurveObject": object.getChildOfType(CurveObject);
default: null;
}
}
function contains(o: Object, name: String): Object {

View File

@ -13,6 +13,6 @@ class GetChildrenNode extends LogicNode {
if (object == null) return null;
return object.children;
return from == 0 ? object.children : object.children.length;
}
}

View File

@ -16,7 +16,9 @@ class GetContactsNode extends LogicNode {
#if lnx_physics
var physics = leenkx.trait.physics.PhysicsWorld.active;
var rbs = physics.getContacts(object.getTrait(RigidBody));
var rb = object.getTrait(RigidBody);
if (rb == null) return null;
var rbs = physics.getContacts(rb);
var obs = [];
if (rbs != null) for (rb in rbs) if (rb != null) obs.push(rb.object);

View File

@ -0,0 +1,39 @@
package leenkx.logicnode;
import iron.object.Object;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavCrowd;
#end
class GetCrowdDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
#if lnx_navigation
var crowdAgent: NavCrowd = object.getTrait(NavCrowd);
if (crowdAgent == null) return null;
return switch(from){
case 0: crowdAgent.navMeshId;
case 1: crowdAgent.crowdAgentVelocity();
case 2: crowdAgent.crowdAgentMaxSpeed();
case 3: crowdAgent.crowdAgentMaxAcceleration();
case 4: crowdAgent.turnSpeed;
case 5: crowdAgent.crowdAgentPosition();
case 6: crowdAgent.crowdAgentNextPath();
case 7: @:privateAccess crowdAgent.agentID;
case 8: crowdAgent.crowdAgentPath();
default: null;
}
#else
return null;
#end
}
}

View File

@ -0,0 +1,33 @@
package leenkx.logicnode;
import iron.object.CurveObject;
import iron.math.Vec4;
class GetCurveDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var curve: CurveObject = inputs[0].get();
if (curve == null) return null;
return
switch (from) {
case 0:
curve.splinesLength;
case 1:
curve.equidistantSamples;
case 2:
curve.visible;
case 3:
curve.data.strength;
case 4:
new Vec4(curve.data.color[0], curve.data.color[1], curve.data.color[2], curve.data.color[3]);
case 5:
curve.curveMesh;
default:
null;
}
}
}

View File

@ -0,0 +1,36 @@
package leenkx.logicnode;
import iron.object.CurveObject;
import iron.math.Vec4;
class GetCurveSplineNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var curve: CurveObject = inputs[0].get();
var index: Int = inputs[1].get();
if (index > curve.splinesLength) return null;
switch(from){
case 0:
var points: Array<Vec4> = [];
var worldMat = curve.transform.world;
for (point in curve.data.splines[index].points){
var p = new Vec4(point.co[0], point.co[1], point.co[2]);
p.applymat(worldMat);
points.push(p);
}
return points;
case 1:
return curve.data.splines[index].closed;
case 2:
return curve.data.splines[index].resolution;
}
return null;
}
}

View File

@ -15,7 +15,10 @@ class GetFirstContactNode extends LogicNode {
#if lnx_physics
var physics = leenkx.trait.physics.PhysicsWorld.active;
var rbs = physics.getContacts(object.getTrait(RigidBody));
var rb = object.getTrait(RigidBody);
if (rb == null) return null;
var rbs = physics.getContacts(rb);
if (rbs != null && rbs.length > 0) return rbs[0].object;
#end

View File

@ -8,6 +8,6 @@ class GetGroupNode extends LogicNode {
override function get(from: Int): Dynamic {
var groupName: String = inputs[0].get();
return iron.Scene.active.getGroup(groupName);
return from == 0 ? iron.Scene.active.getGroup(groupName) : iron.Scene.active.getGroup(groupName).length;
}
}

View File

@ -38,10 +38,10 @@ class GetImageColorNode extends LogicNode {
renderTarget.g2.color = Color.White;
if (property0 == 'Render' || property0 == 'Render&Render2D'){
if (leenkx.renderpath.RenderPathCreator.finalTarget != null){
var img: Image = iron.RenderPath.active.renderTargets.get("buf").image;
renderTarget.g2.drawScaledImage(img, 0, 0, iron.App.w(), iron.App.h());
}
if (leenkx.renderpath.RenderPathCreator.finalTarget != null){
var img: Image = iron.RenderPath.active.renderTargets.get("buf").image;
renderTarget.g2.drawScaledImage(img, 0, 0, iron.App.w(), iron.App.h());
}
}
if (Image.renderTargetsInvertedY()){
@ -75,7 +75,7 @@ class GetImageColorNode extends LogicNode {
var pixels = renderTarget.getPixels();
var k = j * renderTarget.width + i;
#if kha_krom
var l = k;
#elseif kha_html5
@ -84,11 +84,11 @@ class GetImageColorNode extends LogicNode {
var r = pixels.get(l * 4 + 0)/255;
var g = pixels.get(l * 4 + 1)/255;
var b = pixels.get(l * 4 + 2)/255;
var b = pixels.get(l * 4 + 2)/255;
var a = pixels.get(l * 4 + 3)/255;
var v = new Vec4(r, g, b, a);
return v;
}

View File

@ -0,0 +1,52 @@
package leenkx.logicnode;
import iron.system.Input;
import iron.system.Time;
class GetKeyboardNode extends LogicNode {
public var property0: String;
var activeKey: String = "";
var lastTime: Float = -1.0;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnUpdate(update);
}
function update() {
var keyboard = Input.getKeyboard();
var found = false;
for (k in iron.system.Keyboard.keys) {
var b = false;
switch (property0) {
case "started":
b = keyboard.started(k);
case "down":
b = keyboard.down(k);
case "released":
b = keyboard.released(k);
}
if (b) {
if (property0 == "started" || property0 == "released") {
var currentTime = Time.time();
if (currentTime == lastTime && Time.delta != 0) continue;
lastTime = currentTime;
}
activeKey = k;
found = true;
break;
}
}
if (found) {
runOutput(0);
}
}
override function get(from: Int): Dynamic {
return activeKey;
}
}

View File

@ -0,0 +1,37 @@
package leenkx.logicnode;
import iron.object.LightObject;
class GetLightDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var light: LightObject = inputs[0].get();
if (light.data == null) return null;
return switch (from) {
case 0:
return iron.data.LightData.typeToInt(light.data.raw.type);
#if lnx_single_point
case 1:
return light.data.raw.type == "sun" ? light.data.raw.strength / 0.325 : light.data.raw.strength / 0.01;
case 2:
return new iron.math.Vec4(light.data.raw.color[0], light.data.raw.color[1], light.data.raw.color[2]);
#else
case 1:
return light.data.raw.type == "sun" ? light.data.raw.strength / 0.325 : light.strength / 0.01;
case 2:
return light.data.raw.type == "sun" ? new iron.math.Vec4(light.data.raw.color[0], light.data.raw.color[1], light.data.raw.color[2]) : light.color;
#end
case 3:
light.data.raw.cast_shadow;
default:
null;
}
}
}

View File

@ -0,0 +1,31 @@
package leenkx.logicnode;
import iron.Scene;
import iron.data.MaterialData;
import iron.object.Object;
import leenkx.trait.internal.UniformsManager;
class GetMaterialImageParamNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var perObject: Bool = inputs[1].get();
var mat: MaterialData = inputs[2].get();
var link: String = inputs[3].get();
if (mat == null || link == null) return null;
if (!perObject) {
object = Scene.active.root;
}
if (object == null) return null;
var val = @:privateAccess UniformsManager.getObjectTextureLink(object, mat, link);
return val != null ? val : null;
}
}

View File

@ -0,0 +1,31 @@
package leenkx.logicnode;
import iron.Scene;
import iron.data.MaterialData;
import iron.object.Object;
import leenkx.trait.internal.UniformsManager;
class GetMaterialRgbParamNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var perObject: Bool = inputs[1].get();
var mat: MaterialData = inputs[2].get();
var link: String = inputs[3].get();
if (mat == null || link == null) return null;
if (!perObject) {
object = Scene.active.root;
}
if (object == null) return null;
var val = @:privateAccess UniformsManager.getObjectVec3Link(object, mat, link);
return val != null ? val : null;
}
}

View File

@ -0,0 +1,31 @@
package leenkx.logicnode;
import iron.Scene;
import iron.data.MaterialData;
import iron.object.Object;
import leenkx.trait.internal.UniformsManager;
class GetMaterialValueParamNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var perObject: Bool = inputs[1].get();
var mat: MaterialData = inputs[2].get();
var link: String = inputs[3].get();
if (mat == null || link == null) return 0.0;
if (!perObject) {
object = Scene.active.root;
}
if (object == null) return 0.0;
var val = @:privateAccess UniformsManager.getObjectFloatLink(object, mat, link);
return val != null ? val : 0.0;
}
}

View File

@ -1,8 +1,5 @@
package leenkx.logicnode;
import iron.data.SceneFormat;
import iron.object.Object;
class GetObjectByUidNode extends LogicNode {
public function new(tree: LogicTree) {

View File

@ -0,0 +1,27 @@
package leenkx.logicnode;
import iron.object.MeshObject;
import iron.Scene;
class GetObjectCameraDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var mo: MeshObject = cast inputs[0].get();
if (mo == null) return null;
if ((from == 0 && mo.cameraDistance == null) || (from == 1 && mo.screenSize == 0)) {
var cam = Scene.active.camera;
mo.computeCameraDistance(cam.transform.worldx(), cam.transform.worldy(), cam.transform.worldz());
if (from == 1) {
mo.computeScreenSize(cam);
}
}
return from == 0 ? mo.cameraDistance : mo.screenSize;
}
}

View File

@ -5,6 +5,8 @@ import iron.math.Vec4;
class GetObjectGeomNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
@ -14,13 +16,30 @@ class GetObjectGeomNode extends LogicNode {
if (object == null) return null;
if (from == 5)
return object.vertex_groups;
var worldMat = object.transform.world;
if (from == 5) {
if (property0 == "Global") {
var vertexGroups = new Map<String, Array<Vec4>>();
for (key in object.vertexGroups.keys()) {
var vp = [];
for (p in object.vertexGroups.get(key)) {
var p = new Vec4(p.x, p.y, p.z, p.w);
p.applymat(worldMat);
vp.push(p);
}
vertexGroups.set(key, vp);
}
return vertexGroups;
}
else
return object.vertexGroups;
}
if (from == 6){
var keys = [];
if (object.vertex_groups != null)
for (key in object.vertex_groups.keys())
if (object.vertexGroups != null)
for (key in object.vertexGroups.keys())
keys.push(key);
return keys;
@ -36,8 +55,21 @@ class GetObjectGeomNode extends LogicNode {
var normals = object.data.geom.normals.values;
for (i in 0...Std.int(positions.length/4)){
pos.push(new Vec4(positions[i*4]*scl/32767, positions[i*4+1]*scl/32767, positions[i*4+2]*scl/32767, 1));
nor.push(new Vec4(normals[i*2]/32767, normals[i*2+1]/32767, positions[i*4+3]/32767, 1));
var p = new Vec4(positions[i*4]*scl/32767, positions[i*4+1]*scl/32767, positions[i*4+2]*scl/32767, 1);
var n = new Vec4(normals[i*2]/32767, normals[i*2+1]/32767, positions[i*4+3]/32767, 1);
if (property0 == "Global") {
p.applymat(worldMat);
var m = worldMat.clone();
m.getInverse(m);
m.transpose3x3();
m._30 = 0; m._31 = 0; m._32 = 0;
n.applymat(m);
n.normalize();
}
pos.push(p);
nor.push(n);
}
if (from == 0)

View File

@ -0,0 +1,43 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.object.MeshObject;
import kha.arrays.Float32Array;
class GetObjectInstancedNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic{
var object: Object =inputs[0].get();
if (object == null) return null;
var geom = cast(object, MeshObject).data.geom;
return
switch(from){
case 0: geom.instanced;
case 1: @:privateAccess geom.data.raw.instanced_type;
case 2: geom.instanceCount;
case 3: geom.instanceStride;
case 4: toArray(@:privateAccess geom.data.raw.instanced_data);
default: null;
}
}
public static function toArray(elements: Float32Array): Array<Float>{
if (elements == null) return null;
var len = elements.length;
var nid: Array<Float> = [];
for (i in 0...len) {
nid[i] = elements[i];
}
return nid;
}
}

View File

@ -1,13 +1,7 @@
package leenkx.logicnode;
import iron.data.SceneFormat;
import iron.object.Object;
class GetObjectNode extends LogicNode {
/** Scene from which to take the object **/
public var property0: Null<String>;
public function new(tree: LogicTree) {
super(tree);
}

View File

@ -0,0 +1,28 @@
package leenkx.logicnode;
import iron.object.MeshObject;
class GetObjectShapeKeyNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_morph_target
var object: Dynamic = inputs[0].get();
var shapeKey: String = inputs[1].get();
assert(Error, object != null, "Object should not be null");
var morph = cast(object, MeshObject).morphTarget;
assert(Error, morph != null, "Object does not have shape keys");
if (morph.morphMap.exists(shapeKey))
return morph.morphWeights.get(morph.morphMap.get(shapeKey));
#end
return 0.0;
runOutput(0);
}
}

View File

@ -11,6 +11,8 @@ class GetObjectTraitsNode extends LogicNode {
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
if (object == null) return null;
return object.traits;
return
from == 0 ? object.name != null ? object.traits : inputs[0].get().root.children[0].traits :
object.name != null ? object.traits.length : inputs[0].get().root.children[0].traits.length;
}
}

View File

@ -62,6 +62,8 @@ class GetParticleDataNode extends LogicNode {
@:privateAccess psys.lapTime;
case 18:
@:privateAccess psys.count;
case 19:
cast(mo.particleChildren[slot], Object);
default:
null;
}

View File

@ -1,33 +0,0 @@
package leenkx.logicnode;
#if lnx_audio
import iron.object.SpeakerObject;
import kha.audio1.AudioChannel;
#end
class GetPositionSpeakerNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_audio
var object: SpeakerObject = cast(inputs[0].get(), SpeakerObject);
if (object == null || object.sound == null) return 0.0;
if (object.channels.length == 0) return 0.0;
var channel = object.channels[0];
var position = 0.0;
if (channel != null) {
position = @:privateAccess channel.get_position();
}
return position;
#else
return 0.0;
#end
}
}

View File

@ -1,6 +1,7 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
import leenkx.trait.physics.RigidBody;
class GetRigidBodyDataNode extends LogicNode {
@ -16,33 +17,30 @@ class GetRigidBodyDataNode extends LogicNode {
#if lnx_physics
var rb = object.getTrait(RigidBody);
if (rb == null) return null;
return switch (from) {
case 0:
rb == null ? return false : return true;
case 1:
rb.group;
case 2:
rb.mask;
case 3:
rb.animated;
case 4:
rb.staticObj;
case 5:
rb.angularDamping;
case 6:
rb.linearDamping;
case 7:
rb.friction;
case 8:
rb.mass;
//case 9: ; // collision shape
//case 10: ; // activation state
//case 11: ; // is gravity enabled
//case 12: ; // angular factor
//case 13: ; // linear factor
default:
null;
case 0: true;
case 1: rb.group;
case 2: rb.mask;
case 3: rb.animated;
case 4: rb.staticObj;
case 5: rb.linearDamping;
case 6: rb.angularDamping;
case 7: rb.friction;
case 8: rb.angularFriction;
case 9: rb.mass;
case 10: (rb.body.getCollisionFlags() & 4) != 0;
case 11: rb.restitution;
case 12: rb.getGravity().length() > 0.0001;
case 13: rb.getGravity();
case 14:
var lf = @:privateAccess rb.linearFactors;
return new Vec4(lf[0], lf[1], lf[2]);
case 15:
var af = @:privateAccess rb.angularFactors;
return new Vec4(af[0], af[1], af[2]);
default: null;
}
#end

View File

@ -0,0 +1,47 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
#if lnx_physics_soft
import leenkx.trait.physics.bullet.SoftBody;
#end
class GetSoftBodyDataNode extends LogicNode {
var friction: Float;
var damping: Float;
var pressure: Float;
var linearStiffness: Float;
var angularStiffness: Float;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var obj: Object = inputs[0].get();
if (obj == null) return null;
#if lnx_physics_soft
var sb = obj.getTrait(SoftBody);
if (sb == null) return null;
return switch (from) {
case 0: true; // Has SB
case 1: sb.mass;
case 2: sb.bend;
case 3: sb.shape;
case 4: sb.margin;
case 5: new Vec4(sb.vertOffsetX, sb.vertOffsetY, sb.vertOffsetZ);
case 6: sb.friction;
case 7: sb.damping;
case 8: sb.pressure;
case 9: sb.linearStiffness;
case 10: sb.angularStiffness;
default: null;
}
#end
return null;
}
}

View File

@ -0,0 +1,48 @@
package leenkx.logicnode;
#if lnx_audio
import iron.object.SpeakerObject;
import kha.audio1.AudioChannel;
#end
class GetSpeakerDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_audio
var object: SpeakerObject = cast(inputs[0].get(), SpeakerObject);
switch(from){
case 0:
return object.volume;
case 1:
return object.data.pitch;
case 2:
return object.channels.length;
case 3:
var len: Array<Float> = null;
if (object.channels.length > 0){
len = [];
for (channel in object.channels)
len.push(channel.length);
}
return len;
case 4:
var pos: Array<Float> = null;
if (object.channels.length > 0){
pos = [];
for (channel in object.channels)
pos.push(channel.position);
}
return pos;
default:
return null;
}
#else
return null;
#end
}
}

View File

@ -0,0 +1,35 @@
package leenkx.logicnode;
import iron.object.LightObject;
class GetSpotLightDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var light: LightObject = inputs[0].get();
if (light == null) return null;
#if lnx_spot
if (light.data.raw.type == "spot"){
#if lnx_single_point
if (from == 0)
return Math.acos(light.data.raw.spot_size) * 2;
else
return light.data.raw.spot_blend * 10;
#else
if (from == 0)
return Math.acos(light.size) * 2;
else
return light.blend * 10;
#end
}
#end
return null;
}
}

View File

@ -12,9 +12,9 @@ class GetTilesheetFlipNode extends LogicNode {
var object: MeshObject = inputs[0].get();
if (object == null) return null;
if (object.tilesheet == null) return null;
if (from == 0) return object.tilesheet.flipX;
if (from == 1) return object.tilesheet.flipY;
if (object.activeTilesheet == null) return null;
if (from == 0) return object.activeTilesheet.flipX;
if (from == 1) return object.activeTilesheet.flipY;
return null;
}

View File

@ -11,9 +11,9 @@ class GetTilesheetStateNode extends LogicNode {
override function get(from: Int): Dynamic {
var object: MeshObject = inputs[0].get();
if (object == null || object.tilesheet == null) return null;
if (object == null || object.activeTilesheet == null) return null;
var tilesheet = object.tilesheet;
var tilesheet = object.activeTilesheet;
return switch (from) {
case 0: object.name; // Return object name since tilesheet is embedded

View File

@ -17,6 +17,7 @@ class GetTraitNode extends LogicNode {
if (object == null) return null;
if (cname == null) cname = cast Type.resolveClass(Main.projectPackage + "." + name);
if (cname == null) cname = cast Type.resolveClass(Main.projectPackage + ".node." + name);
if (cname == null) cname = cast Type.resolveClass(name);
return object.getTrait(cname);
}

View File

@ -10,9 +10,10 @@ class GetTransformNode extends LogicNode {
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var relative: Bool = inputs[1].get();
if (object == null) return null;
return object.transform.world;
return relative && object.parent != null ? object.transform.local : object.transform.world;
}
}

View File

@ -0,0 +1,34 @@
package leenkx.logicnode;
class GetWorldDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var world = iron.Scene.active.world.raw;
return switch (from) {
case 0:
world.name;
case 1:
world.turbidity != null ? world.probe.strength * 10 : world.probe.strength;
case 2:
intToColor(world.background_color);
default:
null;
}
return null;
}
function intToColor(val: Int): Array<Float> {
var a: Float = ((val >>> 24) & 0xff) / 255.0;
var r: Float = ((val >> 16) & 0xff) / 255.0;
var g: Float = ((val >> 8) & 0xff) / 255.0;
var b: Float = (val & 0xff) / 255.0;
return [r, g, b, a];
}
}

View File

@ -7,6 +7,7 @@ class GetWorldStrengthNode extends LogicNode {
}
override function get(from: Int): Dynamic {
return iron.Scene.active.world.raw.probe.strength;
var world = iron.Scene.active.world.raw;
return world.turbidity != null ? world.probe.strength * 10 : world.probe.strength;
}
}

View File

@ -1,82 +1,48 @@
package leenkx.logicnode;
#if lnx_physics
import leenkx.trait.physics.PhysicsWorld;
#end
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
import leenkx.trait.NavAgent;
#end
import iron.object.Object;
import iron.math.Vec4;
class GoToLocationNode extends LogicNode {
var object: Object;
var location: Vec4;
var speed: Float;
var turnDuration: Float;
var heightOffset: Float;
var useRaycast: Bool;
var rayCastDepth: Float;
var rayCastMask: Int;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
object = inputs[1].get();
location = inputs[2].get();
speed = inputs[3].get();
turnDuration = inputs[4].get();
heightOffset = inputs[5].get();
useRaycast = inputs[6].get();
rayCastDepth = inputs[7].get();
rayCastMask = inputs[8].get();
assert(Error, object != null, "The object input not be null");
assert(Error, location != null, "The location to navigate to must not be null");
assert(Error, speed != null, "Speed of Nav Agent should not be null");
var navMeshId: String = inputs[1].get();
var object: Object = inputs[2].get();
var location: Vec4 = inputs[3].get();
var speed: Float = inputs[4].get();
var turnDuration: Float = inputs[5].get();
var heightOffset: Float = inputs[6].get();
assert(Warning, speed >= 0, "Speed of Nav Agent should be positive");
assert(Error, turnDuration != null, "Turn Duration of Nav Agent should not be null");
assert(Warning, turnDuration >= 0, "Turn Duration of Nav Agent should be positive");
#if lnx_navigation
var from = object.transform.world.getLoc();
var to = location;
#if lnx_navigation
var activeNavMesh: NavMesh = Navigation.active.navMeshes.get(navMeshId);
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
assert(Error, Navigation.active.navMeshes.length > 0, "No Navigation Mesh Present");
Navigation.active.navMeshes[0].findPath(from, to, function(path: Array<iron.math.Vec4>) {
var agent: leenkx.trait.NavAgent = object.getTrait(leenkx.trait.NavAgent);
assert(Error, agent != null, "Object does not have a NavAgent trait");
agent.speed = speed;
agent.turnDuration = turnDuration;
agent.heightOffset = heightOffset;
agent.tickPos = tickPos;
agent.tickRot = tickRot;
agent.setPath(path);
});
#end
activeNavMesh.findPath(object.transform.world.getLoc(), location, function(path: Array<Vec4>) {
var agent: NavAgent = object.getTrait(NavAgent);
assert(Error, agent != null, "Object does not have a NavAgent trait");
agent.navMeshId = navMeshId;
agent.speed = speed;
agent.turnDuration = turnDuration;
agent.heightOffset = heightOffset;
agent.setPath(path);
});
#end
runOutput(0);
}
function tickPos(){
#if lnx_physics
if(useRaycast) setAgentHeight();
#end
runOutput(1);
}
function tickRot(){
runOutput(2);
}
function setAgentHeight(){
#if lnx_physics
var fromLoc = object.transform.world.getLoc();
var toLoc = fromLoc.clone();
toLoc.z += rayCastDepth;
var hit = PhysicsWorld.active.rayCast(fromLoc, toLoc, rayCastMask);
if(hit != null) object.transform.loc.z = hit.pos.z + heightOffset;
#end
}
}

View File

@ -11,6 +11,6 @@ class GroupNode extends LogicNode {
}
override function get(from: Int): Dynamic {
return Scene.active.getGroup(property0);
return from == 0 ? Scene.active.getGroup(property0) : Scene.active.getGroup(property0).length;
}
}

View File

@ -17,14 +17,16 @@ class HasContactArrayNode extends LogicNode {
#if lnx_physics
var physics = leenkx.trait.physics.PhysicsWorld.active;
var rb1 = object1.getTrait(RigidBody);
var rbs = physics.getContacts(rb1);
if (rb1 != null && rbs != null) {
for (object2 in objects) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
return true;
if (rb1 != null){
var rbs = physics.getContacts(rb1);
if (rbs != null) {
for (object2 in objects) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
return true;
}
}
}
}

View File

@ -27,6 +27,12 @@ class LogicTree extends iron.Trait {
public function add() {}
public override function remove() {
if (paused)
_remove = null;
super.remove();
}
public var paused = false;
public function pause() {
@ -36,6 +42,7 @@ class LogicTree extends iron.Trait {
if (_fixedUpdate != null) for (f in _fixedUpdate) iron.App.removeFixedUpdate(f);
if (_update != null) for (f in _update) iron.App.removeUpdate(f);
if (_lateUpdate != null) for (f in _lateUpdate) iron.App.removeLateUpdate(f);
if (_render2D != null) for (f in _render2D) iron.App.removeRender2D(f);
}
public function resume() {
@ -45,5 +52,6 @@ class LogicTree extends iron.Trait {
if (_fixedUpdate != null) for (f in _fixedUpdate) iron.App.notifyOnFixedUpdate(f);
if (_update != null) for (f in _update) iron.App.notifyOnUpdate(f);
if (_lateUpdate != null) for (f in _lateUpdate) iron.App.notifyOnLateUpdate(f);
if (_render2D != null) for (f in _render2D) iron.App.notifyOnRender2D(f);
}
}

View File

@ -2,13 +2,20 @@ package leenkx.logicnode;
import iron.math.Vec4;
import iron.math.Quat;
import iron.math.Mat4;
class LookAtNode extends LogicNode {
public var property0: String;
var v1 = new Vec4();
var v2 = new Vec4();
var q = new Quat();
var m = Mat4.identity();
var f = new Vec4();
var r = new Vec4();
var u = new Vec4();
var z = new Vec4();
var vx = new Vec4();
var vy = new Vec4();
var vz = new Vec4();
public function new(tree: LogicTree) {
super(tree);
@ -18,25 +25,48 @@ class LookAtNode extends LogicNode {
var vfrom: Vec4 = inputs[0].get();
var vto: Vec4 = inputs[1].get();
if (vfrom == null || vto == null) return null;
f.setFrom(vto).sub(vfrom).normalize();
z.set(0, 0, 1);
if (Math.abs(f.dot(z)) > 0.9999) {
z.set(0, 1, 0);
}
r.crossvecs(f, z).normalize();
u.crossvecs(r, f).normalize();
switch (property0) {
case "X":
v1.set(1, 0, 0);
vx.setFrom(f);
vy.set(-r.x, -r.y, -r.z);
vz.setFrom(u);
case "-X":
v1.set(-1, 0, 0);
vx.set(-f.x, -f.y, -f.z);
vy.setFrom(r);
vz.setFrom(u);
case "Y":
v1.set(0, 1, 0);
vx.setFrom(r);
vy.setFrom(f);
vz.setFrom(u);
case "-Y":
v1.set(0, -1, 0);
vx.set(-r.x, -r.y, -r.z);
vy.set(-f.x, -f.y, -f.z);
vz.setFrom(u);
case "Z":
v1.set(0, 0, 1);
vx.setFrom(r);
vy.set(-u.x, -u.y, -u.z);
vz.setFrom(f);
case "-Z":
v1.set(0, 0, -1);
vx.setFrom(r);
vy.setFrom(u);
vz.set(-f.x, -f.y, -f.z);
}
v2.setFrom(vto).sub(vfrom).normalize();
q.fromTo(v1, v2);
m._00 = vx.x; m._01 = vx.y; m._02 = vx.z;
m._10 = vy.x; m._11 = vy.y; m._12 = vy.z;
m._20 = vz.x; m._21 = vz.y; m._22 = vz.z;
q.fromRotationMat(m);
return q;
}
}

View File

@ -6,17 +6,18 @@ class MapRangeNode extends LogicNode {
super(tree);
}
override function get(from: Int): kha.FastFloat {
var value = inputs[0].get();
var fromMin = inputs[1].get();
var fromMax = inputs[2].get();
var toMin = inputs[3].get();
var toMax = inputs[4].get();
override function get(from: Int): Dynamic {
var value: Float = inputs[0].get();
var fromMin: Float = inputs[1].get();
var fromMax: Float = inputs[2].get();
var toMin: Float = inputs[3].get();
var toMax: Float = inputs[4].get();
if (value == null || fromMin == null || fromMax == null || toMin == null || toMax == null) return null;
var deltaFrom = fromMax - fromMin;
if (deltaFrom == 0) return (toMin + toMax) / 2.0;
//Implements https://stackoverflow.com/a/5732390
var slope = (toMax - toMin) / (fromMax - fromMin);
//https://stackoverflow.com/a/5732390
var slope = (toMax - toMin) / deltaFrom;
return toMin + slope * (value - fromMin);
}
}

View File

@ -16,9 +16,43 @@ class MaterialNode extends LogicNode {
}
override function get(from: Int): Dynamic {
if (property0 != null) {
iron.data.Data.getMaterial(iron.Scene.active.raw.name, property0, function(mat: MaterialData) {
value = mat;
if (property0 != null && value == null) {
var currentSceneName = iron.Scene.active.raw.name;
iron.data.Data.getSceneRaw(currentSceneName, function(currentFormat: iron.data.SceneFormat.TSceneFormat) {
var foundInCurrent = false;
if (currentFormat.material_datas != null) {
for (matData in currentFormat.material_datas) {
if (matData.name == property0) {
foundInCurrent = true;
iron.data.Data.getMaterial(currentSceneName, property0, function(mat: MaterialData) {
value = mat;
});
break;
}
}
}
if (!foundInCurrent) {
for (sceneName in leenkx.system.Starter.scenes) {
if (sceneName == currentSceneName) continue;
iron.data.Data.getSceneRaw(sceneName, function(sceneFormat: iron.data.SceneFormat.TSceneFormat) {
if (sceneFormat.material_datas != null) {
for (matData in sceneFormat.material_datas) {
if (matData.name == property0) {
iron.data.Data.getMaterial(sceneName, property0, function(mat: MaterialData) {
value = mat;
});
break;
}
}
}
});
if (value != null) break;
}
}
});
}

View File

@ -0,0 +1,16 @@
package leenkx.logicnode;
import iron.math.Vec4;
class MathConstantsNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override public function get(index: Int): Dynamic {
if (index == 0) return Math.NEGATIVE_INFINITY;
else if (index == 1) return Math.POSITIVE_INFINITY;
else return Math.PI;
}
}

View File

@ -98,7 +98,18 @@ class MathNode extends LogicNode {
}
case "Ping-Pong":
r = pingpong(inputs[0].get(), inputs[1].get());
}
case "Hyperbolic Sine":
var x = inputs[0].get();
r = (Math.exp(x) - Math.exp(-x)) / 2;
case "Hyperbolic Cosine":
var x = inputs[0].get();
r = (Math.exp(x) + Math.exp(-x)) / 2;
case "Hyperbolic Tangent":
var x = inputs[0].get();
var sinh = (Math.exp(x) - Math.exp(-x)) / 2;
var cosh = (Math.exp(x) + Math.exp(-x)) / 2;
r = sinh / cosh;
}
// Clamp
if (property1) r = r < 0.0 ? 0.0 : (r > 1.0 ? 1.0 : r);

View File

@ -1,28 +0,0 @@
package leenkx.logicnode;
import iron.math.Mat4;
class MatrixMathNode extends LogicNode {
public var property0: String;
var m = Mat4.identity();
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var m1: Mat4 = inputs[0].get();
var m2: Mat4 = inputs[1].get();
if (m1 == null || m2 == null) return null;
m.setFrom(m1);
switch (property0) {
case "Multiply":
m.multmat(m2);
}
return m;
}
}

View File

@ -1,9 +1,12 @@
package leenkx.logicnode;
import iron.system.Time;
class MergedKeyboardNode extends LogicNode {
public var property0: String;
public var property1: String;
var lastTime: Float = -1.0;
public function new(tree: LogicTree) {
super(tree);
@ -22,7 +25,14 @@ class MergedKeyboardNode extends LogicNode {
case "released":
b = keyboard.released(property1);
}
if (b) runOutput(0);
if (b) {
if (property0 == "started" || property0 == "released") {
var currentTime = Time.time();
if (currentTime == lastTime && Time.delta != 0) return;
lastTime = currentTime;
}
runOutput(0);
}
}
override function get(from: Int): Dynamic {

View File

@ -4,11 +4,14 @@ package leenkx.logicnode;
import leenkx.trait.internal.DebugConsole;
#end
import iron.system.Time;
class MergedMouseNode extends LogicNode {
public var property0: String;
public var property1: String;
public var property2: Bool;
var lastTime: Float = -1.0;
public function new(tree: LogicTree) {
super(tree);
@ -33,7 +36,14 @@ class MergedMouseNode extends LogicNode {
case "moved":
b = mouse.moved;
}
if (b) runOutput(0);
if (b) {
if (property0 == "started" || property0 == "released") {
var currentTime = Time.time();
if (currentTime == lastTime && Time.delta != 0) return;
lastTime = currentTime;
}
runOutput(0);
}
}
override function get(from: Int): Dynamic {

View File

@ -1,8 +1,11 @@
package leenkx.logicnode;
import iron.system.Time;
class MergedSurfaceNode extends LogicNode {
public var property0: String;
var lastTime: Float = -1.0;
public function new(tree: LogicTree) {
super(tree);
@ -23,7 +26,14 @@ class MergedSurfaceNode extends LogicNode {
case "moved":
b = surface.moved;
}
if (b) runOutput(0);
if (b) {
if (property0 == "started" || property0 == "released") {
var currentTime = Time.time();
if (currentTime == lastTime && Time.delta != 0) return;
lastTime = currentTime;
}
runOutput(0);
}
}
override function get(from: Int): Dynamic {

View File

@ -1,9 +1,12 @@
package leenkx.logicnode;
import iron.system.Time;
class MergedVirtualButtonNode extends LogicNode {
public var property0: String;
public var property1: String;
var lastTime: Float = -1.0;
public function new(tree: LogicTree) {
super(tree);
@ -23,7 +26,14 @@ class MergedVirtualButtonNode extends LogicNode {
case "released":
b = vb.released;
}
if (b) runOutput(0);
if (b) {
if (property0 == "started" || property0 == "released") {
var currentTime = Time.time();
if (currentTime == lastTime && Time.delta != 0) return;
lastTime = currentTime;
}
runOutput(0);
}
}
override function get(from: Int): Dynamic {

View File

@ -1,25 +1,40 @@
package leenkx.logicnode;
import iron.math.Vec4;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
#end
import iron.object.Object;
import iron.math.Vec4;
class NavigableLocationNode extends LogicNode {
var loc: Vec4;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_navigation
assert(Error, Navigation.active.navMeshes.length > 0, "No Navigation Mesh Present");
Navigation.active.navMeshes[0].getRandomPoint(function(p: Vec4) {
loc = p;
});
#end
return loc;
#if lnx_navigation
var object: Object = inputs[0].get();
var v = new iron.math.Vec4();
var centerLoc: Vec4 = object.transform.world.getLoc();
var dim: Vec4 = object.transform.dim;
var v = new Vec4(
centerLoc.x + dim.x * 0.5 * (Math.random() * 2.0 - 1.0),
centerLoc.y + dim.y * 0.5 * (Math.random() * 2.0 - 1.0),
centerLoc.z + dim.z * 0.5 * (Math.random() * 2.0 - 1.0)
);
var activeNavMesh: NavMesh = object.getTrait(NavMesh);
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
return activeNavMesh.getClosestPoint(v);
#end
return null;
}
}

View File

@ -7,6 +7,7 @@ class OnContactArrayNode extends LogicNode {
public var property0: String;
var lastContact = false;
var contactObjects: Array<Object> = [];
public function new(tree: LogicTree) {
super(tree);
@ -19,28 +20,30 @@ class OnContactArrayNode extends LogicNode {
var objects: Array<Object> = inputs[1].get();
if (object1 == null) object1 = tree.object;
if (objects == null)return;
if (objects == null) return;
var contact = false;
var currentContacts: Array<Object> = [];
#if lnx_physics
var physics = leenkx.trait.physics.PhysicsWorld.active;
var rb1 = object1.getTrait(RigidBody);
var rbs = physics.getContacts(rb1);
if (rb1 != null && rbs != null) {
for (object2 in objects) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
contact = true;
break;
if (rb1 != null){
var rbs = physics.getContacts(rb1);
if (rbs != null) {
for (object2 in objects) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
currentContacts.push(object2);
break;
}
}
}
if (contact) break;
}
}
#end
var contact = currentContacts.length > 0;
var b = false;
switch (property0) {
case "begin":
@ -52,7 +55,13 @@ class OnContactArrayNode extends LogicNode {
}
lastContact = contact;
contactObjects = currentContacts;
if (b) runOutput(0);
}
override function get(from: Int): Dynamic {
if (from == 1) return contactObjects;
return contactObjects.length > 0 ? contactObjects[0] : null;
}
}

View File

@ -6,7 +6,13 @@ class OnRender2DNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnRender2D(onRender2D);
#if lnx_ui
tree.notifyOnInit(initNode);
#end
}
function initNode() {
tree.notifyOnRender2D(onRender2D, inputs[0].get());
}
function onRender2D(g: kha.graphics2.Graphics) {
@ -15,4 +21,8 @@ class OnRender2DNode extends LogicNode {
runOutput(0);
RenderToTexture.g = null;
}
override function get(from: Int): Dynamic {
return onRender2D;
}
}

View File

@ -11,7 +11,7 @@ class PauseActionNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
if (object == null) return;
if (object == null){ runOutput(0); return; }
var animation = object.animation;
if (animation == null) animation = object.getBoneAnimation(object.uid);

View File

@ -11,7 +11,7 @@ class PauseSoundNode extends LogicNode {
override function run(from: Int) {
#if lnx_audio
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
if (object == null) return;
if (object == null){ runOutput(0); return; }
object.pause();
#end
runOutput(0);

View File

@ -11,9 +11,10 @@ class PauseTilesheetNode extends LogicNode {
override function run(from: Int) {
var object: MeshObject = inputs[1].get();
if (object == null || object.tilesheet == null) return;
if (object == null){ runOutput(0); return; }
if (object.activeTilesheet == null) return;
object.tilesheet.pause();
object.activeTilesheet.pause();
runOutput(0);
}

View File

@ -1,33 +1,94 @@
package leenkx.logicnode;
#if lnx_navigation
import leenkx.trait.navigation.Navigation;
import leenkx.trait.NavMesh;
#end
#if lnx_physics
import leenkx.trait.physics.PhysicsWorld;
import leenkx.trait.physics.RigidBody;
#end
import iron.object.Object;
import iron.math.Vec4;
import iron.math.RayCaster;
import iron.Scene;
class PickLocationNode extends LogicNode {
var loc = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var coords: Vec4 = inputs[1].get();
var x: Int = inputs[1].get();
var y: Int = inputs[2].get();
if (object == null || coords == null) return null;
var loc = new Vec4();
#if lnx_physics
var physics = leenkx.trait.physics.PhysicsWorld.active;
var b = physics.pickClosest(coords.x, coords.y);
var rb = object.getTrait(leenkx.trait.physics.RigidBody);
#if lnx_navigation
var activeNavMesh: NavMesh = object.getTrait(NavMesh);
var useChildren = activeNavMesh != null && activeNavMesh.combineImmidiateChildren;
#end
if (rb != null && b == rb) {
var p = physics.hitPointWorld;
loc.set(p.x, p.y, p.z);
return loc;
#if lnx_physics
var rb = object.getTrait(RigidBody);
if (rb != null){
var physics = PhysicsWorld.active;
var b = physics.pickClosest(x, y);
var hit = false;
if (b == rb)
hit = true;
if (!hit) {
#if lnx_navigation
if (useChildren) {
for (child in object.children) {
if (child.raw.type != "mesh_object") continue;
var childRb = child.getTrait(RigidBody);
if (childRb != null && childRb == b) {
hit = true;
break;
}
}
}
#end
}
if (hit) {
var p = physics.hitPointWorld;
loc.set(p.x, p.y, p.z);
return loc;
}
else
return null;
}
#end
#end
#if lnx_navigation
assert(Error, activeNavMesh != null, "No Navigation Mesh Present");
loc = RayCaster.boxIntersectObject(object, x, y, Scene.active.camera);
if (loc == null && useChildren) {
for (child in object.children) {
if (child.raw.type != "mesh_object") continue;
loc = RayCaster.boxIntersectObject(child, x, y, Scene.active.camera);
if (loc != null) break;
}
}
return loc != null ? activeNavMesh.getClosestPoint(loc) : null;
#end
return null;
}
}

View File

@ -50,7 +50,7 @@ class PlayActionFromNode extends LogicNode {
loop = inputs[7].get();
reverse = inputs[8].get();
if (object == null) return;
if (object == null){ runOutput(0); return; }
animation = object.animation;
if (animation == null) animation = object.getBoneAnimation(object.uid);
@ -63,7 +63,7 @@ class PlayActionFromNode extends LogicNode {
#if lnx_skin
if (animation.isSkinned){
for(a in animation.armature.actions)
if (a.name == actionR) isnew = false;
if (a.name == actionR){ isnew = false; break; }
if (isnew){
for(a in animation.armature.actions)
@ -156,7 +156,7 @@ class PlayActionFromNode extends LogicNode {
var oactions = cast(animation, ObjectAnimation).oactions;
for (a in oactions)
if (a != null && a.objects[0].name == actionR) isnew = false;
if (a != null && a.objects[0].name == actionR){ isnew = false; break; }
if (isnew){
for (a in oactions){

Some files were not shown because too many files have changed in this diff Show More