From 0b5bb877fb3c587f33d3058fc2b62b0f0f1e57de Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:35:22 +0000 Subject: [PATCH 01/12] Add leenkx/blender/lnx/logicnode/particle/__init__.py --- leenkx/blender/lnx/logicnode/particle/__init__.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 leenkx/blender/lnx/logicnode/particle/__init__.py diff --git a/leenkx/blender/lnx/logicnode/particle/__init__.py b/leenkx/blender/lnx/logicnode/particle/__init__.py new file mode 100644 index 0000000..a6d363e --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/__init__.py @@ -0,0 +1,3 @@ +from lnx.logicnode.lnx_nodes import add_node_section + +add_node_section(name='default', category='Particle') \ No newline at end of file From c3c89c320b7b37f0549090988fce55f9f70026aa Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:36:22 +0000 Subject: [PATCH 02/12] Upload files to "leenkx/blender/lnx/logicnode/particle" --- .../particle/LN_add_particle_to_object.py | 41 +++++++++++++ .../lnx/logicnode/particle/LN_get_particle.py | 14 +++++ .../particle/LN_get_particle_data.py | 31 ++++++++++ .../LN_remove_particle_from_object.py | 33 +++++++++++ .../particle/LN_set_particle_data.py | 58 +++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_add_particle_to_object.py create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_get_particle.py create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_get_particle_data.py create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_remove_particle_from_object.py create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_set_particle_data.py diff --git a/leenkx/blender/lnx/logicnode/particle/LN_add_particle_to_object.py b/leenkx/blender/lnx/logicnode/particle/LN_add_particle_to_object.py new file mode 100644 index 0000000..59431b3 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_add_particle_to_object.py @@ -0,0 +1,41 @@ +from lnx.logicnode.lnx_nodes import * + +class AddParticleToObjectNode(LnxLogicTreeNode): + """Sets the speed of the given particle source.""" + bl_idname = 'LNAddParticleToObjectNode' + bl_label = 'Add Particle To Object' + lnx_version = 1 + + def remove_extra_inputs(self, context): + while len(self.inputs) > 1: + self.inputs.remove(self.inputs[-1]) + if self.property0 == 'Scene': + self.add_input('LnxStringSocket', 'Scene From Name') + self.add_input('LnxStringSocket', 'Object From Name') + else: + self.add_input('LnxNodeSocketObject', 'Object From') + self.add_input('LnxIntSocket', 'Slot') + self.add_input('LnxNodeSocketObject', 'Object To') + self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True) + + + property0: HaxeEnumProperty( + 'property0', + items = [('Scene Active', 'Scene Active', 'Scene Active'), + ('Scene', 'Scene', 'Scene')], + name='', default='Scene Active', update=remove_extra_inputs) + + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Object From') + self.add_input('LnxIntSocket', 'Slot') + self.add_input('LnxNodeSocketObject', 'Object To') + self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True) + + self.add_output('LnxNodeSocketAction', 'Out') + + def draw_buttons(self, context, layout): + layout.prop(self, 'property0') + + diff --git a/leenkx/blender/lnx/logicnode/particle/LN_get_particle.py b/leenkx/blender/lnx/logicnode/particle/LN_get_particle.py new file mode 100644 index 0000000..d0de058 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_get_particle.py @@ -0,0 +1,14 @@ +from lnx.logicnode.lnx_nodes import * + +class GetParticleNode(LnxLogicTreeNode): + """Returns the Particle Systems of an object.""" + bl_idname = 'LNGetParticleNode' + bl_label = 'Get Particle' + lnx_version = 1 + + def lnx_init(self, context): + self.inputs.new('LnxNodeSocketObject', 'Object') + + self.outputs.new('LnxNodeSocketArray', 'Names') + self.outputs.new('LnxIntSocket', 'Length') + self.outputs.new('LnxBoolSocket', 'Render Emitter') \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/particle/LN_get_particle_data.py b/leenkx/blender/lnx/logicnode/particle/LN_get_particle_data.py new file mode 100644 index 0000000..01ef6d0 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_get_particle_data.py @@ -0,0 +1,31 @@ +from lnx.logicnode.lnx_nodes import * + +class GetParticleDataNode(LnxLogicTreeNode): + """Returns the data of the given Particle System.""" + bl_idname = 'LNGetParticleDataNode' + bl_label = 'Get Particle Data' + lnx_version = 1 + + def lnx_init(self, context): + self.inputs.new('LnxNodeSocketObject', 'Object') + self.inputs.new('LnxIntSocket', 'Slot') + + self.outputs.new('LnxStringSocket', 'Name') + self.outputs.new('LnxFloatSocket', 'Particle Size') + self.outputs.new('LnxIntSocket', 'Frame Start') + self.outputs.new('LnxIntSocket', 'Frame End') + self.outputs.new('LnxIntSocket', 'Lifetime') + self.outputs.new('LnxFloatSocket', 'Lifetime Random') + self.outputs.new('LnxIntSocket', 'Emit From') + + self.outputs.new('LnxVectorSocket', 'Velocity') + self.outputs.new('LnxFloatSocket', 'Velocity Random') + self.outputs.new('LnxVectorSocket', 'Gravity') + self.outputs.new('LnxFloatSocket', 'Weight Gravity') + + self.outputs.new('LnxFloatSocket', 'Speed') + + self.outputs.new('LnxFloatSocket', 'Time') + self.outputs.new('LnxFloatSocket', 'Lap') + self.outputs.new('LnxFloatSocket', 'Lap Time') + self.outputs.new('LnxIntSocket', 'Count') diff --git a/leenkx/blender/lnx/logicnode/particle/LN_remove_particle_from_object.py b/leenkx/blender/lnx/logicnode/particle/LN_remove_particle_from_object.py new file mode 100644 index 0000000..8bdd0f4 --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_remove_particle_from_object.py @@ -0,0 +1,33 @@ +from lnx.logicnode.lnx_nodes import * + +class RemoveParticleFromObjectNode(LnxLogicTreeNode): + """Remove Particle From Object.""" + bl_idname = 'LNRemoveParticleFromObjectNode' + bl_label = 'Remove Particle From Object' + lnx_version = 1 + + def remove_extra_inputs(self, context): + while len(self.inputs) > 2: + self.inputs.remove(self.inputs[-1]) + if self.property0 == 'Slot': + self.add_input('LnxIntSocket', 'Slot') + if self.property0 == 'Name': + self.add_input('LnxStringSocket', 'Name') + + property0: HaxeEnumProperty( + 'property0', + items = [('Slot', 'Slot', 'Slot'), + ('Name', 'Name', 'Name'), + ('All', 'All', 'All')], + name='', default='Slot', update=remove_extra_inputs) + + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Object') + self.add_input('LnxIntSocket', 'Slot') + + self.add_output('LnxNodeSocketAction', 'Out') + + def draw_buttons(self, context, layout): + layout.prop(self, 'property0') \ No newline at end of file diff --git a/leenkx/blender/lnx/logicnode/particle/LN_set_particle_data.py b/leenkx/blender/lnx/logicnode/particle/LN_set_particle_data.py new file mode 100644 index 0000000..805ac2b --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_set_particle_data.py @@ -0,0 +1,58 @@ +from lnx.logicnode.lnx_nodes import * + +class SetParticleDataNode(LnxLogicTreeNode): + """Sets the parameters of the given particle system.""" + bl_idname = 'LNSetParticleDataNode' + bl_label = 'Set Particle Data' + lnx_version = 1 + + def remove_extra_inputs(self, context): + while len(self.inputs) > 3: + self.inputs.remove(self.inputs[-1]) + if self.property0 == 'Particle Size': + self.add_input('LnxFloatSocket', 'Particle Size') + if self.property0 == 'Frame End': + self.add_input('LnxIntSocket', 'Frame End') + if self.property0 == 'Frame Start': + self.add_input('LnxIntSocket', 'Frame Start') + if self.property0 == 'Lifetime': + self.add_input('LnxIntSocket', 'Lifetime') + if self.property0 == 'Lifetime Random': + self.add_input('LnxFloatSocket', 'Lifetime Random') + if self.property0 == 'Emit From': + self.add_input('LnxIntSocket', 'Emit From') + if self.property0 == 'Velocity': + self.add_input('LnxVectorSocket', 'Velocity') + if self.property0 == 'Velocity Random': + self.add_input('LnxFloatSocket', 'Velocity Random') + if self.property0 == 'Weight Gravity': + self.add_input('LnxFloatSocket', 'Weight Gravity') + if self.property0 == 'Speed': + self.add_input('LnxFloatSocket', 'Speed') + + + property0: HaxeEnumProperty( + 'property0', + items = [('Particle Size', 'Particle Size', 'for the system'), + ('Frame Start', 'Frame Start', 'for the system'), + ('Frame End', 'Frame End', 'for the system'), + ('Lifetime', 'Lifetime', 'for the instance'), + ('Lifetime Random', 'Lifetime Random', 'for the system'), + ('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'), + ('Velocity', 'Velocity', 'for the instance'), + ('Velocity Random', 'Velocity Random', 'for the system'), + ('Weight Gravity', 'Weight Gravity', 'for the instance'), + ('Speed', 'Speed', 'for the instance')], + name='', default='Speed', update=remove_extra_inputs) + + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Object') + self.add_input('LnxIntSocket', 'Slot') + self.add_input('LnxFloatSocket', 'Speed', default_value=1.0) + + self.add_output('LnxNodeSocketAction', 'Out') + + def draw_buttons(self, context, layout): + layout.prop(self, 'property0') From 727d82f26842691262f49117cfa78ddcab0ef67a Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:39:10 +0000 Subject: [PATCH 03/12] Upload files to "leenkx/blender/lnx/logicnode/particle" --- .../particle/LN_set_particle_speed.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 leenkx/blender/lnx/logicnode/particle/LN_set_particle_speed.py diff --git a/leenkx/blender/lnx/logicnode/particle/LN_set_particle_speed.py b/leenkx/blender/lnx/logicnode/particle/LN_set_particle_speed.py new file mode 100644 index 0000000..a99d77e --- /dev/null +++ b/leenkx/blender/lnx/logicnode/particle/LN_set_particle_speed.py @@ -0,0 +1,22 @@ +from lnx.logicnode.lnx_nodes import * + +class SetParticleSpeedNode(LnxLogicTreeNode): + """Sets the speed of the given particle source.""" + bl_idname = 'LNSetParticleSpeedNode' + bl_label = 'Set Particle Speed' + lnx_version = 2 + + def lnx_init(self, context): + self.add_input('LnxNodeSocketAction', 'In') + self.add_input('LnxNodeSocketObject', 'Object') + self.add_input('LnxIntSocket', 'Slot') + self.add_input('LnxFloatSocket', 'Speed', default_value=1.0) + + self.add_output('LnxNodeSocketAction', 'Out') + + + def get_replacement_node(self, node_tree: bpy.types.NodeTree): + if self.lnx_version not in (0, 1): + raise LookupError() + + return NodeReplacement.Identity(self) From d988ce8c9988029c799c1ee350c8347a29b05416 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:39:32 +0000 Subject: [PATCH 04/12] Delete leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py --- .../logicnode/animation/LN_set_particle_speed.py | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py diff --git a/leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py b/leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py deleted file mode 100644 index 54903a9..0000000 --- a/leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py +++ /dev/null @@ -1,14 +0,0 @@ -from lnx.logicnode.lnx_nodes import * - -class SetParticleSpeedNode(LnxLogicTreeNode): - """Sets the speed of the given particle source.""" - bl_idname = 'LNSetParticleSpeedNode' - bl_label = 'Set Particle Speed' - lnx_version = 1 - - def lnx_init(self, context): - self.add_input('LnxNodeSocketAction', 'In') - self.add_input('LnxNodeSocketObject', 'Object') - self.add_input('LnxFloatSocket', 'Speed', default_value=1.0) - - self.add_output('LnxNodeSocketAction', 'Out') From 61b8f21037ef97858a15f696cd4012f5b27f5bd0 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:42:53 +0000 Subject: [PATCH 05/12] Update leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx --- leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx b/leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx index fc108d2..5d36d61 100644 --- a/leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx +++ b/leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx @@ -11,13 +11,16 @@ class SetParticleSpeedNode extends LogicNode { override function run(from: Int) { #if lnx_particles var object: Object = inputs[1].get(); - var speed: Float = inputs[2].get(); + var slot: Int = inputs[2].get(); + var speed: Float = inputs[3].get(); if (object == null) return; var mo = cast(object, iron.object.MeshObject); - var psys = mo.particleSystems.length > 0 ? mo.particleSystems[0] : null; - if (psys == null) mo.particleOwner.particleSystems[0]; + var psys = mo.particleSystems != null ? mo.particleSystems[slot] : + mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; + + if (psys == null) return; psys.speed = speed; From fc093eca3e807251240d31f173eeeeb99727356f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:46:21 +0000 Subject: [PATCH 06/12] Upload files to "leenkx/Sources/leenkx/logicnode" --- .../logicnode/AddParticleToObjectNode.hx | 99 +++++++++++++++++++ .../leenkx/logicnode/GetParticleDataNode.hx | 66 +++++++++++++ .../leenkx/logicnode/GetParticleNode.hx | 38 +++++++ .../logicnode/RemoveParticleFromObjectNode.hx | 64 ++++++++++++ .../leenkx/logicnode/SetParticleDataNode.hx | 75 ++++++++++++++ 5 files changed, 342 insertions(+) create mode 100644 leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx create mode 100644 leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx create mode 100644 leenkx/Sources/leenkx/logicnode/GetParticleNode.hx create mode 100644 leenkx/Sources/leenkx/logicnode/RemoveParticleFromObjectNode.hx create mode 100644 leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx diff --git a/leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx b/leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx new file mode 100644 index 0000000..ae2ff19 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/AddParticleToObjectNode.hx @@ -0,0 +1,99 @@ +package leenkx.logicnode; + +import iron.data.SceneFormat.TSceneFormat; +import iron.data.Data; +import iron.object.Object; + +class AddParticleToObjectNode extends LogicNode { + + public var property0: String; + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + #if lnx_particles + + if (property0 == 'Scene Active'){ + var objFrom: Object = inputs[1].get(); + var slot: Int = inputs[2].get(); + var objTo: Object = inputs[3].get(); + + if (objFrom == null || objTo == null) return; + + var mobjFrom = cast(objFrom, iron.object.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: psys.r.name}); + + mobjTo.render_emitter = inputs[4].get(); + + iron.Scene.active.spawnObject(psys.data.raw.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; + } + }); + + var oslot: Int = mobjTo.particleSystems.length-1; + var opsys = mobjTo.particleSystems[oslot]; + opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo); + + } else { + var sceneName: String = inputs[1].get(); + var objectName: String = inputs[2].get(); + var slot: Int = inputs[3].get(); + + var mobjTo: Object = inputs[4].get(); + var mobjTo = cast(mobjTo, iron.object.MeshObject); + + #if lnx_json + sceneName += ".json"; + #elseif lnx_compress + sceneName += ".lz4"; + #end + + 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(); + + 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); + + var oslot: Int = mobjTo.particleSystems.length-1; + var opsys = mobjTo.particleSystems[oslot]; + opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo); + + break; + } + } + + }); + + } + + #end + + runOutput(0); + } +} diff --git a/leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx b/leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx new file mode 100644 index 0000000..2b2b669 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/GetParticleDataNode.hx @@ -0,0 +1,66 @@ +package leenkx.logicnode; + +import iron.object.Object; + +class GetParticleDataNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function get(from: Int): Dynamic { + var object: Object = inputs[0].get(); + var slot: Int = inputs[1].get(); + + if (object == null) return null; + + #if lnx_particles + + var mo = cast(object, iron.object.MeshObject); + + var psys = mo.particleSystems != null ? mo.particleSystems[slot] : + mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; + + if (psys == null) return null; + + return switch (from) { + case 0: + psys.r.name; + case 1: + psys.r.particle_size; + case 2: + psys.r.frame_start; + case 3: + psys.r.frame_end; + case 4: + psys.lifetime; + case 5: + psys.r.lifetime; + case 6: + psys.r.emit_from; + case 7: + new iron.math.Vec3(psys.alignx*2, psys.aligny*2, psys.alignz*2); + case 8: + psys.r.factor_random; + case 9: + new iron.math.Vec3(psys.gx, psys.gy, psys.gz); + case 10: + psys.r.weight_gravity; + case 11: + psys.speed; + case 12: + psys.time; + case 13: + psys.lap; + case 14: + psys.lapTime; + case 15: + psys.count; + default: + null; + } + #end + + return null; + } +} diff --git a/leenkx/Sources/leenkx/logicnode/GetParticleNode.hx b/leenkx/Sources/leenkx/logicnode/GetParticleNode.hx new file mode 100644 index 0000000..1a2df24 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/GetParticleNode.hx @@ -0,0 +1,38 @@ +package leenkx.logicnode; + +import iron.object.Object; + +class GetParticleNode 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; + + #if lnx_particles + + var mo = cast(object, iron.object.MeshObject); + + switch (from) { + case 0: + var names: Array = []; + if (mo.particleSystems != null) + for (psys in mo.particleSystems) + names.push(psys.r.name); + return names; + case 1: + return mo.particleSystems != null ? mo.particleSystems.length : 0; + case 2: + return mo.render_emitter; + default: + null; + } + #end + + return null; + } +} diff --git a/leenkx/Sources/leenkx/logicnode/RemoveParticleFromObjectNode.hx b/leenkx/Sources/leenkx/logicnode/RemoveParticleFromObjectNode.hx new file mode 100644 index 0000000..17f7ef7 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/RemoveParticleFromObjectNode.hx @@ -0,0 +1,64 @@ +package leenkx.logicnode; + +import iron.object.Object; + +class RemoveParticleFromObjectNode extends LogicNode { + + public var property0: String; + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + #if lnx_particles + var object: Object = inputs[1].get(); + + if (object == null) return; + + var mo = cast(object, iron.object.MeshObject); + + if (mo.particleSystems == null) return; + + if (property0 == 'All'){ + mo.particleSystems = null; + for (c in mo.particleChildren) c.remove(); + mo.particleChildren = null; + mo.particleOwner = null; + mo.render_emitter = true; + } + else { + + var slot: Int = -1; + if (property0 == 'Name'){ + var name: String = inputs[2].get(); + for (i => psys in mo.particleSystems){ + if (psys.r.name == name){ slot = i; break; } + } + } + else slot = inputs[2].get(); + + if (mo.particleSystems.length > slot){ + for (i in slot+1...mo.particleSystems.length){ + var mi = cast(mo.particleChildren[i], iron.object.MeshObject); + mi.particleIndex = mi.particleIndex - 1; + } + mo.particleSystems.splice(slot, 1); + mo.particleChildren[slot].remove(); + mo.particleChildren.splice(slot, 1); + } + + if (slot == 0){ + mo.particleSystems = null; + mo.particleChildren = null; + mo.particleOwner = null; + mo.render_emitter = true; + } + + } + + #end + + runOutput(0); + } +} diff --git a/leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx b/leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx new file mode 100644 index 0000000..acf6071 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetParticleDataNode.hx @@ -0,0 +1,75 @@ +package leenkx.logicnode; + +import iron.object.Object; + +class SetParticleDataNode extends LogicNode { + + public var property0: String; + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + #if lnx_particles + var object: Object = inputs[1].get(); + var slot: Int = inputs[2].get(); + + if (object == null) return; + + var mo = cast(object, iron.object.MeshObject); + + var psys = mo.particleSystems != null ? mo.particleSystems[slot] : + mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; if (psys == null) return; + + switch (property0) { + case 'Particle Size': + psys.r.particle_size = inputs[3].get(); + case 'Frame Start': + psys.r.frame_start = inputs[3].get(); + psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate; + psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate; + case 'Frame End': + psys.r.frame_end = inputs[3].get(); + psys.animtime = (psys.r.frame_end - psys.r.frame_start) / psys.frameRate; + psys.spawnRate = ((psys.r.frame_end - psys.r.frame_start) / psys.count) / psys.frameRate; + case 'Lifetime': + psys.lifetime = inputs[3].get() / psys.frameRate; + case 'Lifetime Random': + psys.r.lifetime_random = inputs[3].get(); + case 'Emit From': + var emit_from: Int = inputs[3].get(); + if (emit_from == 0 || emit_from == 1 || emit_from == 2) { + psys.r.emit_from = emit_from; + psys.setupGeomGpu(mo.particleChildren != null ? mo.particleChildren[slot] : cast(iron.Scene.active.getChild(psys.data.raw.instance_object), iron.object.MeshObject), mo); + } + case 'Velocity': + var vel: iron.math.Vec3 = inputs[3].get(); + psys.alignx = vel.x / 2; + psys.aligny = vel.y / 2; + psys.alignz = vel.z / 2; + case 'Velocity Random': + psys.r.factor_random = inputs[3].get(); + case 'Weight Gravity': + psys.r.weight_gravity = inputs[3].get(); + if (iron.Scene.active.raw.gravity != null) { + psys.gx = iron.Scene.active.raw.gravity[0] * psys.r.weight_gravity; + psys.gy = iron.Scene.active.raw.gravity[1] * psys.r.weight_gravity; + psys.gz = iron.Scene.active.raw.gravity[2] * psys.r.weight_gravity; + } + else { + psys.gx = 0; + psys.gy = 0; + psys.gz = -9.81 * psys.r.weight_gravity; + } + case 'Speed': + psys.speed = inputs[3].get(); + default: + null; + } + + #end + + runOutput(0); + } +} From 7565818d0e532107362ab101ad976f39b351085f Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:47:32 +0000 Subject: [PATCH 07/12] Upload files to "leenkx/Sources/leenkx/logicnode" --- .../logicnode/SetParticleRenderEmitterNode.hx | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 leenkx/Sources/leenkx/logicnode/SetParticleRenderEmitterNode.hx diff --git a/leenkx/Sources/leenkx/logicnode/SetParticleRenderEmitterNode.hx b/leenkx/Sources/leenkx/logicnode/SetParticleRenderEmitterNode.hx new file mode 100644 index 0000000..1125962 --- /dev/null +++ b/leenkx/Sources/leenkx/logicnode/SetParticleRenderEmitterNode.hx @@ -0,0 +1,23 @@ +package leenkx.logicnode; + +import iron.object.Object; + +class SetParticleRenderEmitterNode extends LogicNode { + + public function new(tree: LogicTree) { + super(tree); + } + + override function run(from: Int) { + #if lnx_particles + var object: Object = inputs[1].get(); + + if (object == null) return; + + cast(object, iron.object.MeshObject).render_emitter = inputs[2].get(); + + #end + + runOutput(0); + } +} \ No newline at end of file From 205d4ccc41453e5992dcfc0b233558acb28dedbe Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 21:52:06 +0000 Subject: [PATCH 08/12] Update leenkx/Sources/iron/Scene.hx --- leenkx/Sources/iron/Scene.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/leenkx/Sources/iron/Scene.hx b/leenkx/Sources/iron/Scene.hx index df640e2..75b1f62 100644 --- a/leenkx/Sources/iron/Scene.hx +++ b/leenkx/Sources/iron/Scene.hx @@ -775,6 +775,7 @@ class Scene { // Attach particle systems #if lnx_particles if (o.particle_refs != null) { + cast(object, MeshObject).render_emitter = o.render_emitter; for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref); } #end From ac2507e0ae15e66d19e06ffb289381da084be2b4 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 22:00:56 +0000 Subject: [PATCH 09/12] Update leenkx/Sources/iron/object/MeshObject.hx --- leenkx/Sources/iron/object/MeshObject.hx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/leenkx/Sources/iron/object/MeshObject.hx b/leenkx/Sources/iron/object/MeshObject.hx index 1c42bcd..4711a06 100644 --- a/leenkx/Sources/iron/object/MeshObject.hx +++ b/leenkx/Sources/iron/object/MeshObject.hx @@ -21,6 +21,7 @@ class MeshObject extends Object { public var particleChildren: Array = null; public var particleOwner: MeshObject = null; // Particle object public var particleIndex = -1; + public var render_emitter = true; #end public var cameraDistance: Float; public var screenSize = 0.0; @@ -255,11 +256,11 @@ class MeshObject extends Object { particleSystems[i].update(particleChildren[i], this); } } - if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return; + if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return; + if (particleSystems == null && cullMaterial(context)) return; + #else + if (cullMaterial(context)) return; #end - - if (cullMaterial(context)) return; - // Get lod var mats = materials; var lod = this; From 8066756605d1d00c8aa9cc173963f77ef088d1e5 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 22:02:56 +0000 Subject: [PATCH 10/12] Update leenkx/Sources/iron/object/ParticleSystem.hx --- leenkx/Sources/iron/object/ParticleSystem.hx | 30 ++++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/leenkx/Sources/iron/object/ParticleSystem.hx b/leenkx/Sources/iron/object/ParticleSystem.hx index 6e55a36..2f20990 100644 --- a/leenkx/Sources/iron/object/ParticleSystem.hx +++ b/leenkx/Sources/iron/object/ParticleSystem.hx @@ -18,29 +18,29 @@ class ParticleSystem { public var speed = 1.0; var particles: Array; var ready: Bool; - var frameRate = 24; - var lifetime = 0.0; - var animtime = 0.0; - var time = 0.0; - var spawnRate = 0.0; + public var frameRate = 24; + public var lifetime = 0.0; + public var animtime = 0.0; + public var time = 0.0; + public var spawnRate = 0.0; var seed = 0; - var r: TParticleData; - var gx: Float; - var gy: Float; - var gz: Float; - var alignx: Float; - var aligny: Float; - var alignz: Float; + public var r: TParticleData; + public var gx: Float; + public var gy: Float; + public var gz: Float; + public var alignx: Float; + public var aligny: Float; + public var alignz: Float; var dimx: Float; var dimy: Float; var tilesx: Int; var tilesy: Int; var tilesFramerate: Int; - var count = 0; - var lap = 0; - var lapTime = 0.0; + public var count = 0; + public var lap = 0; + public var lapTime = 0.0; var m = Mat4.identity(); var ownerLoc = new Vec4(); From 9558ded5c4a35883aee465034c3ea0f1123814d3 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 22:03:44 +0000 Subject: [PATCH 11/12] Update leenkx/Sources/iron/object/ParticleSystem.hx --- leenkx/Sources/iron/object/ParticleSystem.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/leenkx/Sources/iron/object/ParticleSystem.hx b/leenkx/Sources/iron/object/ParticleSystem.hx index 2f20990..5c94f08 100644 --- a/leenkx/Sources/iron/object/ParticleSystem.hx +++ b/leenkx/Sources/iron/object/ParticleSystem.hx @@ -149,7 +149,7 @@ class ParticleSystem { // GPU particles transform is attached to owner object } - function setupGeomGpu(object: MeshObject, owner: MeshObject) { + public function setupGeomGpu(object: MeshObject, owner: MeshObject) { var instancedData = new Float32Array(particles.length * 6); var i = 0; From 751f960b82a373d8c429265f951188daabb731d1 Mon Sep 17 00:00:00 2001 From: Onek8 Date: Thu, 22 May 2025 22:06:41 +0000 Subject: [PATCH 12/12] Update leenkx/blender/lnx/logicnode/__init__.py --- leenkx/blender/lnx/logicnode/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/leenkx/blender/lnx/logicnode/__init__.py b/leenkx/blender/lnx/logicnode/__init__.py index ce3969e..ab82a33 100644 --- a/leenkx/blender/lnx/logicnode/__init__.py +++ b/leenkx/blender/lnx/logicnode/__init__.py @@ -47,7 +47,8 @@ def init_categories(): lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion") lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion") lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion") - + lnx_nodes.add_category('Particle', icon='PARTICLE_DATA', section="motion") + lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values") lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values") lnx_nodes.add_category('Database', icon='MESH_CYLINDER', section="values")