Merge pull request #2028 from QuantumCoderQC/rb_nodes
New Add rigid body node
This commit is contained in:
commit
5ff3ec9055
109
Sources/armory/logicnode/AddRigidBodyNode.hx
Normal file
109
Sources/armory/logicnode/AddRigidBodyNode.hx
Normal file
|
@ -0,0 +1,109 @@
|
|||
package armory.logicnode;
|
||||
|
||||
#if arm_physics
|
||||
import armory.trait.physics.bullet.RigidBody.Shape;
|
||||
#end
|
||||
import iron.object.Object;
|
||||
import armory.trait.physics.RigidBody;
|
||||
|
||||
class AddRigidBodyNode extends LogicNode {
|
||||
|
||||
public var property0: String;//Shape
|
||||
public var property1: String;//Advanced
|
||||
public var object: Object;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
object = inputs[1].get();
|
||||
var mass: Float = inputs[2].get();
|
||||
var active: Bool = inputs[3].get();
|
||||
var animated: Bool = inputs[4].get();
|
||||
var trigger: Bool = inputs[5].get();
|
||||
var friction: Float = inputs[6].get();
|
||||
var bounciness: Float = inputs[7].get();
|
||||
var ccd: Bool = inputs[8].get();
|
||||
|
||||
var margin: Bool = false;
|
||||
var marginLen: Float = 0.0;
|
||||
var linDamp: Float = 0.0;
|
||||
var angDamp: Float = 0.0;
|
||||
var useDeactiv: Bool = false;
|
||||
var linearVelThreshold: Float = 0.0;
|
||||
var angVelThreshold: Float = 0.0;
|
||||
var group: Int = 1;
|
||||
var mask: Int = 1;
|
||||
|
||||
var shape: Shape = 1;
|
||||
|
||||
if(property1 == 'true')
|
||||
{
|
||||
margin = inputs[9].get();
|
||||
marginLen = inputs[10].get();
|
||||
linDamp = inputs[11].get();
|
||||
angDamp = inputs[12].get();
|
||||
useDeactiv = inputs[13].get();
|
||||
linearVelThreshold = inputs[14].get();
|
||||
angVelThreshold = inputs[15].get();
|
||||
group = inputs[16].get();
|
||||
mask = inputs[17].get();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (object == null) return;
|
||||
|
||||
#if arm_physics
|
||||
var rb: RigidBody = object.getTrait(RigidBody);
|
||||
if((group < 0) || (group > 32)) group = 1; //Limiting max groups to 32
|
||||
if((mask < 0) || (mask > 32)) mask = 1; //Limiting max masks to 32
|
||||
if(rb == null)
|
||||
{
|
||||
|
||||
switch (property0){
|
||||
|
||||
case 'Box':
|
||||
shape = Box;
|
||||
case 'Sphere':
|
||||
shape = Sphere;
|
||||
case 'Capsule':
|
||||
shape = Capsule;
|
||||
case 'Cone':
|
||||
shape = Cone;
|
||||
case 'Cylinder':
|
||||
shape = Cylinder;
|
||||
case 'Convex Hull':
|
||||
shape = ConvexHull;
|
||||
case 'Mesh':
|
||||
shape = Mesh;
|
||||
}
|
||||
|
||||
rb = new RigidBody(shape, mass, friction, bounciness, group, mask);
|
||||
rb.animated = animated;
|
||||
rb.staticObj = ! active;
|
||||
rb.isTriggerObject(trigger);
|
||||
if(property1 == 'true')
|
||||
{
|
||||
rb.linearDamping = linDamp;
|
||||
rb.angularDamping = angDamp;
|
||||
if(margin) rb.collisionMargin = marginLen;
|
||||
if(useDeactiv) {
|
||||
rb.setDeactivation(true);
|
||||
rb.setDeactivationParams(linearVelThreshold, angVelThreshold, 0.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object.addTrait(rb);
|
||||
}
|
||||
#end
|
||||
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
override function get(from: Int): Object {
|
||||
return object;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ class RigidBody extends iron.Trait {
|
|||
public var destroyed = false;
|
||||
var linearFactors: Array<Float>;
|
||||
var angularFactors: Array<Float>;
|
||||
var useDeactivation: Bool;
|
||||
var deactivationParams: Array<Float>;
|
||||
var ccd = false; // Continuous collision detection
|
||||
public var group = 1;
|
||||
|
@ -96,7 +97,29 @@ class RigidBody extends iron.Trait {
|
|||
this.mask = mask;
|
||||
|
||||
if (params == null) params = [0.04, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0];
|
||||
if (flags == null) flags = [false, false, false, false];
|
||||
/**
|
||||
* params:[ linear damping
|
||||
* angular damping
|
||||
* linear factor X
|
||||
* linear factor Y
|
||||
* linear factor Z
|
||||
* angular factor X
|
||||
* angular factor Y
|
||||
* angular factor Z
|
||||
* collision margin
|
||||
* linear deactivation threshold
|
||||
* angular deactivation thrshold
|
||||
* deactivation time(Not used)]
|
||||
*/
|
||||
|
||||
if (flags == null) flags = [false, false, false, false, true];
|
||||
/**
|
||||
* flags:[ is animated
|
||||
* is trigger
|
||||
* continuous collision detection
|
||||
* is static
|
||||
* use deactivation]
|
||||
*/
|
||||
|
||||
this.linearDamping = params[0];
|
||||
this.angularDamping = params[1];
|
||||
|
@ -108,6 +131,7 @@ class RigidBody extends iron.Trait {
|
|||
this.trigger = flags[1];
|
||||
this.ccd = flags[2];
|
||||
this.staticObj = flags[3];
|
||||
this.useDeactivation = flags[4];
|
||||
|
||||
notifyOnAdd(init);
|
||||
}
|
||||
|
@ -241,7 +265,7 @@ class RigidBody extends iron.Trait {
|
|||
}
|
||||
bodyColl.setRestitution(restitution);
|
||||
|
||||
if (deactivationParams != null) {
|
||||
if ( useDeactivation) {
|
||||
setDeactivationParams(deactivationParams[0], deactivationParams[1], deactivationParams[2]);
|
||||
}
|
||||
else {
|
||||
|
@ -358,6 +382,14 @@ class RigidBody extends iron.Trait {
|
|||
// body.setDeactivationTime(time); // not available in ammo
|
||||
}
|
||||
|
||||
public function setDeactivation(useDeactivation: Bool) {
|
||||
this.useDeactivation = useDeactivation;
|
||||
}
|
||||
|
||||
public function isTriggerObject(isTrigger: Bool) {
|
||||
this.trigger = isTrigger;
|
||||
}
|
||||
|
||||
public function applyForce(force: Vec4, loc: Vec4 = null) {
|
||||
activate();
|
||||
vec1.setValue(force.x, force.y, force.z);
|
||||
|
|
|
@ -2360,7 +2360,7 @@ class ArmoryExporter:
|
|||
if bobject.lock_rotation[2]:
|
||||
az = 0
|
||||
col_margin = str(rb.collision_margin) if rb.use_margin else '0.0'
|
||||
if rb.use_deactivation or bobject.arm_rb_force_deactivation:
|
||||
if rb.use_deactivation:
|
||||
deact_lv = str(rb.deactivate_linear_velocity)
|
||||
deact_av = str(rb.deactivate_angular_velocity)
|
||||
deact_time = str(bobject.arm_rb_deactivation_time)
|
||||
|
@ -2376,11 +2376,12 @@ class ArmoryExporter:
|
|||
col_margin,
|
||||
deact_lv, deact_av, deact_time
|
||||
)
|
||||
body_flags = '[{0}, {1}, {2}, {3}]'.format(
|
||||
body_flags = '[{0}, {1}, {2}, {3}, {4}]'.format(
|
||||
str(rb.kinematic).lower(),
|
||||
str(bobject.arm_rb_trigger).lower(),
|
||||
str(bobject.arm_rb_ccd).lower(),
|
||||
str(is_static).lower()
|
||||
str(is_static).lower(),
|
||||
str(rb.use_deactivation).lower()
|
||||
)
|
||||
x['parameters'].append(body_params)
|
||||
x['parameters'].append(body_flags)
|
||||
|
|
126
blender/arm/logicnode/physics/LN_Add_rigid_body.py
Normal file
126
blender/arm/logicnode/physics/LN_Add_rigid_body.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
from arm.logicnode.arm_nodes import *
|
||||
|
||||
class AddRigidBodyNode(ArmLogicTreeNode):
|
||||
"""Adds a rigid body to an object if not already present.
|
||||
|
||||
@option Advanced: Shows optional advanced options for rigid body.
|
||||
|
||||
@option Shape: Shape of the rigid body including Box, Sphere, Capsule, Cone, Cylinder, Convex Hull and Mesh
|
||||
|
||||
@input Object: Object to which rigid body is added.
|
||||
|
||||
@input Mass: Mass of the rigid body. Must be > 0.
|
||||
|
||||
@input Active: Rigid body actively participates in the physics world and will be affected by collisions
|
||||
|
||||
@input Animated: Rigid body follows animation and will affect other active non-animated rigid bodies.
|
||||
|
||||
@input Trigger: Rigid body behaves as a trigger and detects collision. However, rigd body does not contribute to or receive collissions.
|
||||
|
||||
@input Friction: Surface friction of the rigid body. Minimum value = 0, Preferred max value = 1.
|
||||
|
||||
@input Bounciness: How elastic is the surface of the rigid body. Minimum value = 0, Preferred max value = 1.
|
||||
|
||||
@input Continuous Collision Detection (CCD): Detects for collisions in between frames. Use only for very fast moving objects.
|
||||
|
||||
@input Collision Margin: Enable an external margin for collision detection
|
||||
|
||||
@input Margin: Length of the collision margin. Must be > 0.
|
||||
|
||||
@input Linear Damping: Damping for linear translation. Recommended range 0 to 1.
|
||||
|
||||
@input Angular Damping: Damping for angular translation. Recommended range 0 to 1.
|
||||
|
||||
@input Use Deactivation: Deactive this rigid body when below the Linear and Angular velocity threshold. Enable to improve performance.
|
||||
|
||||
@input Linear Velocity Threshold: Velocity below which decativation occurs if enabled.
|
||||
|
||||
@input Angular Velocity Threshold: Velocity below which decativation occurs if enabled.
|
||||
|
||||
@input Collision Group: A set of rigid bodies that can interact with each other
|
||||
|
||||
@input Collision Mask: Bitmask to filter collisions. Collision can occur between two rigid bodies if they have atleast one bit in common.
|
||||
|
||||
@output Rigid body: Object to which rigid body was added.
|
||||
|
||||
@output Out: activated after rigid body is added.
|
||||
"""
|
||||
|
||||
bl_idname = 'LNAddRigidBodyNode'
|
||||
bl_label = 'Add Rigid Body'
|
||||
arm_version = 1
|
||||
|
||||
NUM_STATIC_INS = 9
|
||||
|
||||
def update_advanced(self, context):
|
||||
"""This is a helper method to allow declaring the `advanced`
|
||||
property before the update_sockets() method. It's not required
|
||||
but then you would need to move the declaration of `advanced`
|
||||
further down."""
|
||||
self.update_sockets(context)
|
||||
|
||||
@property
|
||||
def property1(self):
|
||||
return 'true' if self.property1_ else 'false'
|
||||
|
||||
property1_: BoolProperty(
|
||||
name="Advanced",
|
||||
description="Show advanced options",
|
||||
default=False,
|
||||
update=update_advanced
|
||||
)
|
||||
|
||||
property0: EnumProperty(
|
||||
items = [('Box', 'Box', 'Box'),
|
||||
('Sphere', 'Sphere', 'Sphere'),
|
||||
('Capsule', 'Capsule', 'Capsule'),
|
||||
('Cone', 'Cone', 'Cone'),
|
||||
('Cylinder', 'Cylinder', 'Cylinder'),
|
||||
('Convex Hull', 'Convex Hull', 'Convex Hull'),
|
||||
('Mesh', 'Mesh', 'Mesh')],
|
||||
name='Shape', default='Box')
|
||||
|
||||
def init(self, context):
|
||||
super(AddRigidBodyNode, self).init(context)
|
||||
|
||||
self.add_input('ArmNodeSocketAction', 'In')
|
||||
self.add_input('ArmNodeSocketObject', 'Object')
|
||||
self.add_input('NodeSocketFloat', 'Mass', 1.0)
|
||||
self.add_input('NodeSocketBool', 'Active', True)
|
||||
self.add_input('NodeSocketBool', 'Animated', False)
|
||||
self.add_input('NodeSocketBool', 'Trigger', False)
|
||||
self.add_input('NodeSocketFloat', 'Friction', 0.5)
|
||||
self.add_input('NodeSocketFloat', 'Bounciness', 0.0)
|
||||
self.add_input('NodeSocketBool', 'Continuous Collision Detection', False)
|
||||
self.add_output('ArmNodeSocketAction', 'Out')
|
||||
self.add_output('ArmNodeSocketObject', 'Rigid body')
|
||||
|
||||
self.update_sockets(context)
|
||||
|
||||
def update_sockets(self, context):
|
||||
# It's bad to remove from a list during iteration so we use
|
||||
# this helper list here
|
||||
remove_list = []
|
||||
|
||||
# Remove dynamically placed input sockets
|
||||
for i in range(AddRigidBodyNode.NUM_STATIC_INS, len(self.inputs)):
|
||||
remove_list.append(self.inputs[i])
|
||||
for i in remove_list:
|
||||
self.inputs.remove(i)
|
||||
|
||||
# Add dynamic input sockets
|
||||
if self.property1_:
|
||||
self.add_input('NodeSocketBool', 'Collision Margin', False)
|
||||
self.add_input('NodeSocketFloat', 'Margin', 0.04)
|
||||
self.add_input('NodeSocketFloat', 'Linear Damping', 0.04)
|
||||
self.add_input('NodeSocketFloat', 'Angular Damping', 0.1)
|
||||
self.add_input('NodeSocketBool', 'Use Deacivation')
|
||||
self.add_input('NodeSocketFloat', 'Linear Velocity Threshold', 0.4)
|
||||
self.add_input('NodeSocketFloat', 'Angular Velocity Threshold', 0.5)
|
||||
self.add_input('NodeSocketInt', 'Collision Group', 1)
|
||||
self.add_input('NodeSocketInt', 'Collision Mask', 1)
|
||||
|
||||
|
||||
def draw_buttons(self, context, layout):
|
||||
layout.prop(self, "property1_")
|
||||
layout.prop(self, 'property0')
|
|
@ -276,7 +276,6 @@ def init_properties():
|
|||
bpy.types.Object.arm_rb_linear_factor = FloatVectorProperty(name="Linear Factor", size=3, description="Set to 0 to lock axis", default=[1,1,1])
|
||||
bpy.types.Object.arm_rb_angular_factor = FloatVectorProperty(name="Angular Factor", size=3, description="Set to 0 to lock axis", default=[1,1,1])
|
||||
bpy.types.Object.arm_rb_trigger = BoolProperty(name="Trigger", description="Disable contact response", default=False)
|
||||
bpy.types.Object.arm_rb_force_deactivation = BoolProperty(name="Force Deactivation", description="Force deactivation on all rigid bodies for performance", default=True)
|
||||
bpy.types.Object.arm_rb_deactivation_time = FloatProperty(name="Deactivation Time", description="Delay putting rigid body into sleep", default=0.0)
|
||||
bpy.types.Object.arm_rb_ccd = BoolProperty(name="Continuous Collision Detection", description="Improve collision for fast moving objects", default=False)
|
||||
bpy.types.Object.arm_animation_enabled = BoolProperty(name="Animation", description="Enable skinning & timeline animation", default=True)
|
||||
|
|
|
@ -152,7 +152,6 @@ class ARM_PT_PhysicsPropsPanel(bpy.types.Panel):
|
|||
layout.prop(obj, 'arm_rb_linear_factor')
|
||||
layout.prop(obj, 'arm_rb_angular_factor')
|
||||
layout.prop(obj, 'arm_rb_trigger')
|
||||
layout.prop(obj, 'arm_rb_force_deactivation')
|
||||
layout.prop(obj, 'arm_rb_ccd')
|
||||
|
||||
if obj.soft_body != None:
|
||||
|
|
Loading…
Reference in a new issue