Compare commits
128 Commits
id_copy_re
...
particles_
Author | SHA1 | Date | |
---|---|---|---|
69f990ad7e | |||
911fe9dfa2 | |||
55cf7703fd | |||
f5abbee52a | |||
01a2253dfd | |||
4684f2c70d | |||
5a6eccfe43 | |||
79fc66872a | |||
b7d3160133 | |||
da8b4f9112 | |||
e2d7123674 | |||
843efe48ab | |||
bb3cf1ded0 | |||
137fa8a40b | |||
547f42156e | |||
54fe3f0285 | |||
6821bec4eb | |||
fd5b195ea7 | |||
3113007682 | |||
6529e53f40 | |||
d82c6ce507 | |||
0211fc88f9 | |||
5235a9ea75 | |||
e93e2abae6 | |||
13876fafbc | |||
7253c6752b | |||
772b08b8aa | |||
d4af9c8e6a | |||
3ae43a2ce2 | |||
1edcfc363e | |||
f077d9f57c | |||
839149ea90 | |||
6a3705690f | |||
7c666d168f | |||
667728788d | |||
2e9c9415eb | |||
2fbb7a7937 | |||
6cf17ddc48 | |||
93da0edf0c | |||
dc60ec7505 | |||
4472309bdd | |||
f948f57a98 | |||
0480a26d37 | |||
a5f193fe51 | |||
1d6638d077 | |||
dc4dd96db2 | |||
ddf86fb42c | |||
c56fb3d108 | |||
e93309556b | |||
39ce10c2f5 | |||
b6ff000ec2 | |||
7f8997783f | |||
335ff9331a | |||
3887c0f2f1 | |||
30d3fae8b7 | |||
10d17ae2b1 | |||
97011304e4 | |||
1c84174ae9 | |||
2a4b80101b | |||
89c74dfcf1 | |||
1275e68c0e | |||
3033fdd502 | |||
6b4719e1e0 | |||
b8f54307fc | |||
2ec54df635 | |||
f4344cdfa5 | |||
f3d1522272 | |||
eee0f75b1f | |||
fe0bd22bcf | |||
dc93c57b41 | |||
c991cd78e7 | |||
6f9afa9775 | |||
5dd5c883fa | |||
e93d2e0625 | |||
02e687d02c | |||
6ad40aa1ae | |||
4eda0a6f42 | |||
e1dc85f974 | |||
7209bd4ebd | |||
ad9e4983dc | |||
5d4ae82cc0 | |||
4b90b80c70 | |||
f2bdf4bd4c | |||
2496ab7f5d | |||
5f3ae1c0d6 | |||
971d22e5d0 | |||
326a3b20f1 | |||
408be6417d | |||
a5a6bd1c00 | |||
c7f285ca10 | |||
f92590e396 | |||
5e90d3e803 | |||
e750e0fc93 | |||
649c8d6909 | |||
b6ced99abb | |||
5dccaa1ad6 | |||
206a0bd42f | |||
e7561274d7 | |||
fc51e04aec | |||
a0c7ee76a3 | |||
d99ff7fbee | |||
75aff0a75e | |||
689d660adf | |||
d5d5002c49 | |||
05791252b2 | |||
8873e54701 | |||
e775f53b16 | |||
af9e6b7fc5 | |||
34487cd754 | |||
857a403cd2 | |||
e65fb0661d | |||
e1a9f63867 | |||
da63e23ef7 | |||
4f7867247b | |||
1da72ac496 | |||
dce6d75726 | |||
2ab499cd1d | |||
2cba992e9f | |||
e5777ec044 | |||
bc3e02f8fe | |||
46ffd66368 | |||
3fe2dc327e | |||
![]() |
075f6d4cf4 | ||
![]() |
44633c67d1 | ||
![]() |
982c74edf0 | ||
![]() |
dbf603c488 | ||
![]() |
2c0065295a | ||
![]() |
69692fdb0f |
@@ -487,6 +487,7 @@ macro(SETUP_BLENDER_SORTED_LIBS)
|
||||
bf_python_ext
|
||||
bf_python_mathutils
|
||||
bf_python_bmesh
|
||||
bf_python_bparticles
|
||||
bf_freestyle
|
||||
bf_ikplugin
|
||||
bf_modifiers
|
||||
|
@@ -37,6 +37,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* API Notes:
|
||||
* Currently, this API is optimised for Bullet RigidBodies, and doesn't
|
||||
* take into account other Physics Engines. Some tweaking may be necessary
|
||||
@@ -56,6 +58,7 @@ typedef struct rbDynamicsWorld rbDynamicsWorld;
|
||||
|
||||
/* Rigid Body */
|
||||
typedef struct rbRigidBody rbRigidBody;
|
||||
extern size_t rbRigidBodySize;
|
||||
|
||||
/* Collision Shape */
|
||||
typedef struct rbCollisionShape rbCollisionShape;
|
||||
@@ -120,10 +123,10 @@ void RB_world_convex_sweep_test(
|
||||
/* ............ */
|
||||
|
||||
/* Create new RigidBody instance */
|
||||
rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4]);
|
||||
void RB_body_init(rbRigidBody *object, rbCollisionShape *shape, const float loc[3], const float rot[4]);
|
||||
|
||||
/* Delete the given RigidBody instance */
|
||||
void RB_body_delete(rbRigidBody *body);
|
||||
void RB_body_free(rbRigidBody *object);
|
||||
|
||||
/* Settings ------------------------- */
|
||||
|
||||
@@ -137,6 +140,11 @@ void RB_body_set_collision_shape(rbRigidBody *body, rbCollisionShape *shape);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/* Generic flagging */
|
||||
extern int RB_body_get_flags(rbRigidBody *body);
|
||||
extern void RB_body_set_flag(rbRigidBody *body, int flag);
|
||||
extern void RB_body_clear_flag(rbRigidBody *body, int flag);
|
||||
|
||||
/* Mass */
|
||||
float RB_body_get_mass(rbRigidBody *body);
|
||||
void RB_body_set_mass(rbRigidBody *body, float value);
|
||||
|
@@ -81,11 +81,23 @@ struct rbDynamicsWorld {
|
||||
btConstraintSolver *constraintSolver;
|
||||
btOverlapFilterCallback *filterCallback;
|
||||
};
|
||||
|
||||
struct rbRigidBody {
|
||||
btRigidBody *body;
|
||||
rbRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) :
|
||||
body(constructionInfo),
|
||||
col_groups(0),
|
||||
flag(0)
|
||||
{}
|
||||
~rbRigidBody()
|
||||
{}
|
||||
|
||||
btRigidBody body;
|
||||
int col_groups;
|
||||
int flag;
|
||||
};
|
||||
|
||||
size_t rbRigidBodySize = sizeof(rbRigidBody);
|
||||
|
||||
struct rbVert {
|
||||
float x, y, z;
|
||||
};
|
||||
@@ -252,7 +264,7 @@ void RB_dworld_export(rbDynamicsWorld *world, const char *filename)
|
||||
|
||||
void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_groups)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
object->col_groups = col_groups;
|
||||
|
||||
world->dynamicsWorld->addRigidBody(body);
|
||||
@@ -260,7 +272,7 @@ void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_gro
|
||||
|
||||
void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
world->dynamicsWorld->removeRigidBody(body);
|
||||
}
|
||||
@@ -272,7 +284,7 @@ void RB_world_convex_sweep_test(
|
||||
const float loc_start[3], const float loc_end[3],
|
||||
float v_location[3], float v_hitpoint[3], float v_normal[3], int *r_hit)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
btCollisionShape *collisionShape = body->getCollisionShape();
|
||||
/* only convex shapes are supported, but user can specify a non convex shape */
|
||||
if (collisionShape->isConvex()) {
|
||||
@@ -320,9 +332,8 @@ void RB_world_convex_sweep_test(
|
||||
|
||||
/* ............ */
|
||||
|
||||
rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4])
|
||||
void RB_body_init(rbRigidBody *object, rbCollisionShape *shape, const float loc[3], const float rot[4])
|
||||
{
|
||||
rbRigidBody *object = new rbRigidBody;
|
||||
/* current transform */
|
||||
btTransform trans;
|
||||
trans.setOrigin(btVector3(loc[0], loc[1], loc[2]));
|
||||
@@ -331,19 +342,16 @@ rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const floa
|
||||
/* create motionstate, which is necessary for interpolation (includes reverse playback) */
|
||||
btDefaultMotionState *motionState = new btDefaultMotionState(trans);
|
||||
|
||||
/* make rigidbody */
|
||||
btRigidBody::btRigidBodyConstructionInfo rbInfo(1.0f, motionState, shape->cshape);
|
||||
|
||||
object->body = new btRigidBody(rbInfo);
|
||||
|
||||
object->body->setUserPointer(object);
|
||||
|
||||
return object;
|
||||
/* make rigidbody, using placement new to initialize given memory buffer */
|
||||
new (object) rbRigidBody(rbInfo);
|
||||
object->body.setUserPointer(object);
|
||||
}
|
||||
|
||||
void RB_body_delete(rbRigidBody *object)
|
||||
void RB_body_free(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
/* motion state */
|
||||
btMotionState *ms = body->getMotionState();
|
||||
@@ -361,15 +369,15 @@ void RB_body_delete(rbRigidBody *object)
|
||||
body->removeConstraintRef(con);
|
||||
}
|
||||
|
||||
delete body;
|
||||
delete object;
|
||||
/* only call destructor, memory management happens externally */
|
||||
object->~rbRigidBody();
|
||||
}
|
||||
|
||||
/* Settings ------------------------- */
|
||||
|
||||
void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
/* set new collision shape */
|
||||
body->setCollisionShape(shape->cshape);
|
||||
@@ -380,9 +388,24 @@ void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape)
|
||||
|
||||
/* ............ */
|
||||
|
||||
int RB_body_get_flags(rbRigidBody *body)
|
||||
{
|
||||
return body->flag;
|
||||
}
|
||||
|
||||
void RB_body_set_flag(rbRigidBody *body, int flag)
|
||||
{
|
||||
body->flag |= flag;
|
||||
}
|
||||
|
||||
void RB_body_clear_flag(rbRigidBody *body, int flag)
|
||||
{
|
||||
body->flag &= ~flag;
|
||||
}
|
||||
|
||||
float RB_body_get_mass(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
/* there isn't really a mass setting, but rather 'inverse mass'
|
||||
* which we convert back to mass by taking the reciprocal again
|
||||
@@ -397,7 +420,7 @@ float RB_body_get_mass(rbRigidBody *object)
|
||||
|
||||
void RB_body_set_mass(rbRigidBody *object, float value)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
btVector3 localInertia(0, 0, 0);
|
||||
|
||||
/* calculate new inertia if non-zero mass */
|
||||
@@ -413,33 +436,33 @@ void RB_body_set_mass(rbRigidBody *object, float value)
|
||||
|
||||
float RB_body_get_friction(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getFriction();
|
||||
}
|
||||
|
||||
void RB_body_set_friction(rbRigidBody *object, float value)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setFriction(value);
|
||||
}
|
||||
|
||||
|
||||
float RB_body_get_restitution(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getRestitution();
|
||||
}
|
||||
|
||||
void RB_body_set_restitution(rbRigidBody *object, float value)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setRestitution(value);
|
||||
}
|
||||
|
||||
|
||||
float RB_body_get_linear_damping(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getLinearDamping();
|
||||
}
|
||||
|
||||
@@ -450,7 +473,7 @@ void RB_body_set_linear_damping(rbRigidBody *object, float value)
|
||||
|
||||
float RB_body_get_angular_damping(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getAngularDamping();
|
||||
}
|
||||
|
||||
@@ -461,14 +484,14 @@ void RB_body_set_angular_damping(rbRigidBody *object, float value)
|
||||
|
||||
void RB_body_set_damping(rbRigidBody *object, float linear, float angular)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setDamping(linear, angular);
|
||||
}
|
||||
|
||||
|
||||
float RB_body_get_linear_sleep_thresh(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getLinearSleepingThreshold();
|
||||
}
|
||||
|
||||
@@ -479,7 +502,7 @@ void RB_body_set_linear_sleep_thresh(rbRigidBody *object, float value)
|
||||
|
||||
float RB_body_get_angular_sleep_thresh(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
return body->getAngularSleepingThreshold();
|
||||
}
|
||||
|
||||
@@ -490,7 +513,7 @@ void RB_body_set_angular_sleep_thresh(rbRigidBody *object, float value)
|
||||
|
||||
void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setSleepingThresholds(linear, angular);
|
||||
}
|
||||
|
||||
@@ -498,14 +521,14 @@ void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular)
|
||||
|
||||
void RB_body_get_linear_velocity(rbRigidBody *object, float v_out[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
copy_v3_btvec3(v_out, body->getLinearVelocity());
|
||||
}
|
||||
|
||||
void RB_body_set_linear_velocity(rbRigidBody *object, const float v_in[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
body->setLinearVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
|
||||
}
|
||||
@@ -513,27 +536,27 @@ void RB_body_set_linear_velocity(rbRigidBody *object, const float v_in[3])
|
||||
|
||||
void RB_body_get_angular_velocity(rbRigidBody *object, float v_out[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
copy_v3_btvec3(v_out, body->getAngularVelocity());
|
||||
}
|
||||
|
||||
void RB_body_set_angular_velocity(rbRigidBody *object, const float v_in[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
body->setAngularVelocity(btVector3(v_in[0], v_in[1], v_in[2]));
|
||||
}
|
||||
|
||||
void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setLinearFactor(btVector3(x, y, z));
|
||||
}
|
||||
|
||||
void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setAngularFactor(btVector3(x, y, z));
|
||||
}
|
||||
|
||||
@@ -541,7 +564,7 @@ void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z)
|
||||
|
||||
void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
if (kinematic)
|
||||
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||
else
|
||||
@@ -552,7 +575,7 @@ void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic)
|
||||
|
||||
void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
if (use_deactivation)
|
||||
body->forceActivationState(ACTIVE_TAG);
|
||||
else
|
||||
@@ -560,12 +583,12 @@ void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation)
|
||||
}
|
||||
void RB_body_activate(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setActivationState(ACTIVE_TAG);
|
||||
}
|
||||
void RB_body_deactivate(rbRigidBody *object)
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
body->setActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
|
||||
@@ -581,7 +604,7 @@ void RB_body_deactivate(rbRigidBody *object)
|
||||
|
||||
void RB_body_get_transform_matrix(rbRigidBody *object, float m_out[4][4])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
btMotionState *ms = body->getMotionState();
|
||||
|
||||
btTransform trans;
|
||||
@@ -592,7 +615,7 @@ void RB_body_get_transform_matrix(rbRigidBody *object, float m_out[4][4])
|
||||
|
||||
void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float rot[4])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
btMotionState *ms = body->getMotionState();
|
||||
|
||||
/* set transform matrix */
|
||||
@@ -605,7 +628,7 @@ void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float ro
|
||||
|
||||
void RB_body_set_scale(rbRigidBody *object, const float scale[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
/* apply scaling factor from matrix above to the collision shape */
|
||||
btCollisionShape *cshape = body->getCollisionShape();
|
||||
@@ -623,14 +646,14 @@ void RB_body_set_scale(rbRigidBody *object, const float scale[3])
|
||||
|
||||
void RB_body_get_position(rbRigidBody *object, float v_out[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
copy_v3_btvec3(v_out, body->getWorldTransform().getOrigin());
|
||||
}
|
||||
|
||||
void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
copy_quat_btquat(v_out, body->getWorldTransform().getRotation());
|
||||
}
|
||||
@@ -640,7 +663,7 @@ void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
|
||||
|
||||
void RB_body_apply_central_force(rbRigidBody *object, const float v_in[3])
|
||||
{
|
||||
btRigidBody *body = object->body;
|
||||
btRigidBody *body = &object->body;
|
||||
|
||||
body->applyCentralForce(btVector3(v_in[0], v_in[1], v_in[2]));
|
||||
}
|
||||
@@ -863,8 +886,8 @@ static void make_constraint_transforms(btTransform &transform1, btTransform &tra
|
||||
|
||||
rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
|
||||
btVector3 pivot1 = body1->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
|
||||
btVector3 pivot2 = body2->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]);
|
||||
@@ -876,8 +899,8 @@ rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidB
|
||||
|
||||
rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -890,8 +913,8 @@ rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody
|
||||
|
||||
rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -904,8 +927,8 @@ rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody
|
||||
|
||||
rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -918,8 +941,8 @@ rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody
|
||||
|
||||
rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -933,8 +956,8 @@ rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody
|
||||
|
||||
rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -947,8 +970,8 @@ rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *
|
||||
|
||||
rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
@@ -961,8 +984,8 @@ rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigi
|
||||
|
||||
rbConstraint *RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
|
||||
{
|
||||
btRigidBody *body1 = rb1->body;
|
||||
btRigidBody *body2 = rb2->body;
|
||||
btRigidBody *body1 = &rb1->body;
|
||||
btRigidBody *body2 = &rb2->body;
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
|
@@ -1222,5 +1222,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
col.prop(md, "material_offset", text="Material Offset")
|
||||
|
||||
|
||||
def NPARTICLE_SYSTEM(self, layout, ob, md):
|
||||
pass
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
bpy.utils.register_module(__name__)
|
||||
|
@@ -61,10 +61,12 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_modifier_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_nla_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_node_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_nparticle_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_fluidsim.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_force.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_object_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pagedbuffer_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h
|
||||
|
133
source/blender/blenkernel/BKE_nparticle.h
Normal file
133
source/blender/blenkernel/BKE_nparticle.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BKE_NPARTICLE_H
|
||||
#define BKE_NPARTICLE_H
|
||||
|
||||
/** \file BKE_nparticle.h
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
struct Object;
|
||||
struct NParticleSystem;
|
||||
struct NParticleAttribute;
|
||||
struct NParticleState;
|
||||
struct NParticleAttributeState;
|
||||
struct NParticleDisplay;
|
||||
struct NParticleDisplayDupliObject;
|
||||
|
||||
/* XXX where to put this? */
|
||||
typedef uint32_t NParticleID;
|
||||
|
||||
const char *BKE_nparticle_datatype_name(int datatype);
|
||||
|
||||
struct NParticleSystem *BKE_nparticle_system_new(void);
|
||||
void BKE_nparticle_system_free(struct NParticleSystem *psys);
|
||||
struct NParticleSystem *BKE_nparticle_system_copy(struct NParticleSystem *psys);
|
||||
|
||||
void BKE_nparticle_system_set_state(struct NParticleSystem *psys, struct NParticleState *state);
|
||||
|
||||
struct NParticleState *BKE_nparticle_state_new(struct NParticleSystem *psys);
|
||||
struct NParticleState *BKE_nparticle_state_copy(struct NParticleState *state);
|
||||
void BKE_nparticle_state_free(struct NParticleState *state);
|
||||
|
||||
struct NParticleAttribute *BKE_nparticle_attribute_find(struct NParticleSystem *psys, const char *name);
|
||||
struct NParticleAttribute *BKE_nparticle_attribute_new(struct NParticleSystem *psys, const char *name, int datatype, int flag);
|
||||
void BKE_nparticle_attribute_remove(struct NParticleSystem *psys, struct NParticleAttribute *attr);
|
||||
void BKE_nparticle_attribute_remove_all(struct NParticleSystem *psys);
|
||||
void BKE_nparticle_attribute_move(struct NParticleSystem *psys, int from_index, int to_index);
|
||||
struct NParticleAttribute *BKE_nparticle_attribute_copy(struct NParticleSystem *to_psys,
|
||||
struct NParticleSystem *from_psys, struct NParticleAttribute *from_attr);
|
||||
|
||||
int BKE_nparticle_state_num_attributes(struct NParticleState *state);
|
||||
struct NParticleAttributeState *BKE_nparticle_state_find_attribute(struct NParticleState *state, const char *name);
|
||||
struct NParticleAttributeState *BKE_nparticle_state_get_attribute_by_index(struct NParticleState *state, int index);
|
||||
|
||||
int BKE_nparticle_state_num_particles(struct NParticleState *state);
|
||||
|
||||
void *BKE_nparticle_attribute_state_data(struct NParticleAttributeState *attrstate, int index);
|
||||
|
||||
typedef struct NParticleAttributeStateIterator {
|
||||
/* XXX for now is simply a pointer, using ListBase next/prev.
|
||||
* Eventually this will become a hash table iterator.
|
||||
*/
|
||||
struct NParticleAttributeState *attrstate;
|
||||
} NParticleAttributeStateIterator;
|
||||
|
||||
void BKE_nparticle_state_attributes_begin(struct NParticleState *state, struct NParticleAttributeStateIterator *iter);
|
||||
bool BKE_nparticle_state_attribute_iter_valid(struct NParticleAttributeStateIterator *iter);
|
||||
void BKE_nparticle_state_attribute_iter_next(struct NParticleAttributeStateIterator *iter);
|
||||
void BKE_nparticle_state_attribute_iter_end(struct NParticleAttributeStateIterator *iter);
|
||||
|
||||
|
||||
int BKE_nparticle_find_index(struct NParticleState *state, NParticleID id);
|
||||
bool BKE_nparticle_exists(struct NParticleState *state, NParticleID id);
|
||||
int BKE_nparticle_add(struct NParticleState *state, NParticleID id);
|
||||
void BKE_nparticle_remove(struct NParticleState *state, NParticleID id);
|
||||
|
||||
typedef struct NParticleIterator {
|
||||
struct NParticleState *state;
|
||||
int index;
|
||||
} NParticleIterator;
|
||||
|
||||
void BKE_nparticle_iter_init(struct NParticleState *state, struct NParticleIterator *it);
|
||||
void BKE_nparticle_iter_from_id(struct NParticleState *state, struct NParticleIterator *it, NParticleID id);
|
||||
void BKE_nparticle_iter_from_index(struct NParticleState *state, struct NParticleIterator *it, int index);
|
||||
void BKE_nparticle_iter_next(struct NParticleIterator *it);
|
||||
bool BKE_nparticle_iter_valid(struct NParticleIterator *it);
|
||||
|
||||
/*void *BKE_nparticle_iter_get_data(struct NParticleIterator *it, const char *attr);*/
|
||||
int BKE_nparticle_iter_get_int(struct NParticleIterator *it, const char *attr);
|
||||
void BKE_nparticle_iter_set_int(struct NParticleIterator *it, const char *attr, int value);
|
||||
float BKE_nparticle_iter_get_float(struct NParticleIterator *it, const char *attr);
|
||||
void BKE_nparticle_iter_set_float(struct NParticleIterator *it, const char *attr, float value);
|
||||
void BKE_nparticle_iter_get_vector(struct NParticleIterator *it, const char *attr, float *result);
|
||||
void BKE_nparticle_iter_set_vector(struct NParticleIterator *it, const char *attr, const float *value);
|
||||
void BKE_nparticle_iter_get_quaternion(struct NParticleIterator *it, const char *attr, float *result);
|
||||
void BKE_nparticle_iter_set_quaternion(struct NParticleIterator *it, const char *attr, const float *value);
|
||||
void *BKE_nparticle_iter_get_pointer(struct NParticleIterator *it, const char *attr);
|
||||
void BKE_nparticle_iter_set_pointer(struct NParticleIterator *it, const char *attr, void *value);
|
||||
|
||||
BLI_INLINE NParticleID BKE_nparticle_iter_get_id(struct NParticleIterator *it)
|
||||
{
|
||||
return (NParticleID)BKE_nparticle_iter_get_int(it, "id");
|
||||
}
|
||||
|
||||
|
||||
struct NParticleDisplay *BKE_nparticle_display_add(struct NParticleSystem *psys, int type);
|
||||
struct NParticleDisplay *BKE_nparticle_display_copy(struct NParticleSystem *psys, struct NParticleDisplay *display);
|
||||
void BKE_nparticle_display_free(struct NParticleSystem *psys, struct NParticleDisplay *display);
|
||||
|
||||
/* update object transflag for nparticle duplis */
|
||||
void BKE_nparticle_update_object_dupli_flags(struct Object *ob, struct NParticleSystem *psys);
|
||||
|
||||
struct NParticleDisplayDupliObject *BKE_nparticle_display_dupli_object_add(struct NParticleDisplay *display);
|
||||
void BKE_nparticle_display_dupli_object_remove(struct NParticleDisplay *display, struct NParticleDisplayDupliObject *dupli_object);
|
||||
void BKE_nparticle_display_dupli_object_remove_all(struct NParticleDisplay *display);
|
||||
void BKE_nparticle_display_dupli_object_move(struct NParticleDisplay *display, int from_index, int to_index);
|
||||
|
||||
#endif /* BKE_NPARTICLE_H */
|
@@ -29,13 +29,13 @@
|
||||
* \ingroup blenkernel
|
||||
* \brief API for Blender-side Rigid Body stuff
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __BKE_RIGIDBODY_H__
|
||||
#define __BKE_RIGIDBODY_H__
|
||||
|
||||
struct RigidBodyWorld;
|
||||
struct RigidBodyOb;
|
||||
struct rbRigidBody;
|
||||
|
||||
struct Scene;
|
||||
struct Object;
|
||||
@@ -45,28 +45,24 @@ struct Group;
|
||||
/* Memory Management */
|
||||
|
||||
void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw);
|
||||
void BKE_rigidbody_free_object(struct Object *ob);
|
||||
void BKE_rigidbody_free_constraint(struct Object *ob);
|
||||
|
||||
/* ...... */
|
||||
|
||||
struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
|
||||
struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
|
||||
void BKE_rigidbody_relink_constraint(struct RigidBodyCon *rbc);
|
||||
|
||||
/* -------------- */
|
||||
/* Setup */
|
||||
|
||||
/* create Blender-side settings data - physics objects not initialized yet */
|
||||
struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene);
|
||||
struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type);
|
||||
struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
|
||||
|
||||
/* initialize mempools, for readfile */
|
||||
void BKE_rigidbody_world_init_mempool(struct RigidBodyWorld *rbw);
|
||||
|
||||
/* copy */
|
||||
struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw);
|
||||
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
|
||||
|
||||
/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
|
||||
struct rbRigidBody *BKE_rigidbody_body_ensure_alloc(struct RigidBodyWorld *rbw, struct rbRigidBody *body, bool rebuild);
|
||||
void BKE_rigidbody_body_tag_used(struct rbRigidBody *body);
|
||||
void BKE_rigidbody_validate_sim_shape(Object *ob, bool rebuild);
|
||||
void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, bool rebuild);
|
||||
|
||||
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol);
|
||||
@@ -76,27 +72,49 @@ void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_com[3]);
|
||||
/* Utilities */
|
||||
|
||||
struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene);
|
||||
void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob);
|
||||
void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
|
||||
|
||||
/* -------------- */
|
||||
/* Utility Macros */
|
||||
|
||||
/* get mass of Rigid Body Object to supply to RigidBody simulators */
|
||||
#define RBO_GET_MASS(rbo) \
|
||||
((rbo && ((rbo->type == RBO_TYPE_PASSIVE) || (rbo->flag & RBO_FLAG_KINEMATIC) || (rbo->flag & RBO_FLAG_DISABLED))) ? (0.0f) : (rbo->mass))
|
||||
/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */
|
||||
#define RBO_GET_MARGIN(rbo) \
|
||||
((rbo->flag & RBO_FLAG_USE_MARGIN || rbo->shape == RB_SHAPE_CONVEXH || rbo->shape == RB_SHAPE_TRIMESH || rbo->shape == RB_SHAPE_CONE) ? (rbo->margin) : (0.04f))
|
||||
|
||||
/* -------------- */
|
||||
/* Simulation */
|
||||
|
||||
void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle);
|
||||
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
|
||||
bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
|
||||
void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
|
||||
void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
|
||||
void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
|
||||
|
||||
|
||||
/* -------------- */
|
||||
/* Objects (rigidbody_objects.c) */
|
||||
|
||||
/* Main Simulation Sync */
|
||||
|
||||
void BKE_rigidbody_objects_build(struct Scene *scene, struct RigidBodyWorld *rbw, bool rebuild);
|
||||
void BKE_rigidbody_objects_apply(struct Scene *scene, struct RigidBodyWorld *rbw);
|
||||
void BKE_rigidbody_constraints_build(struct Scene *scene, struct RigidBodyWorld *rbw, bool rebuild);
|
||||
void BKE_rigidbody_constraints_apply(struct Scene *scene, struct RigidBodyWorld *rbw);
|
||||
|
||||
/* Transform Utils */
|
||||
|
||||
void BKE_rigidbody_object_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle);
|
||||
void BKE_rigidbody_object_apply_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
|
||||
|
||||
/* Object Data Management */
|
||||
|
||||
struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type);
|
||||
void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob);
|
||||
void BKE_rigidbody_free_object(struct Object *ob);
|
||||
struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
|
||||
|
||||
struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
|
||||
void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
|
||||
void BKE_rigidbody_free_constraint(struct Object *ob);
|
||||
struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
|
||||
void BKE_rigidbody_relink_constraint(struct RigidBodyCon *rbc);
|
||||
|
||||
/* Utilities */
|
||||
|
||||
/* get mass of Rigid Body Object to supply to RigidBody simulators */
|
||||
float BKE_rigidbody_object_mass(struct RigidBodyOb *rbo);
|
||||
/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */
|
||||
float BKE_rigidbody_object_margin(struct RigidBodyOb *rbo);
|
||||
|
||||
#endif /* __BKE_RIGIDBODY_H__ */
|
||||
|
@@ -125,6 +125,7 @@ set(SRC
|
||||
intern/multires.c
|
||||
intern/nla.c
|
||||
intern/node.c
|
||||
intern/nparticle.c
|
||||
intern/object.c
|
||||
intern/object_deform.c
|
||||
intern/object_dupli.c
|
||||
@@ -139,6 +140,7 @@ set(SRC
|
||||
intern/property.c
|
||||
intern/report.c
|
||||
intern/rigidbody.c
|
||||
intern/rigidbody_objects.c
|
||||
intern/sca.c
|
||||
intern/scene.c
|
||||
intern/screen.c
|
||||
@@ -230,6 +232,7 @@ set(SRC
|
||||
BKE_multires.h
|
||||
BKE_nla.h
|
||||
BKE_node.h
|
||||
BKE_nparticle.h
|
||||
BKE_object.h
|
||||
BKE_object_deform.h
|
||||
BKE_ocean.h
|
||||
|
759
source/blender/blenkernel/intern/nparticle.c
Normal file
759
source/blender/blenkernel/intern/nparticle.c
Normal file
@@ -0,0 +1,759 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/blenkernel/intern/nparticle.c
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_utildefines.h" /* XXX stupid, needed by ghash, should be included there ... */
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_pagedbuffer.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
|
||||
#include "BKE_nparticle.h"
|
||||
#include "BKE_rigidbody.h"
|
||||
|
||||
/* XXX TODO make this configurable */
|
||||
#define PAGE_BYTES 65536
|
||||
|
||||
const char *BKE_nparticle_datatype_name(int datatype)
|
||||
{
|
||||
switch (datatype) {
|
||||
case PAR_ATTR_DATATYPE_INTERNAL: return "internal";
|
||||
case PAR_ATTR_DATATYPE_FLOAT: return "float";
|
||||
case PAR_ATTR_DATATYPE_INT: return "int";
|
||||
case PAR_ATTR_DATATYPE_BOOL: return "bool";
|
||||
case PAR_ATTR_DATATYPE_VECTOR: return "vector";
|
||||
case PAR_ATTR_DATATYPE_POINT: return "point";
|
||||
case PAR_ATTR_DATATYPE_NORMAL: return "normal";
|
||||
case PAR_ATTR_DATATYPE_QUATERNION: return "quaternion";
|
||||
case PAR_ATTR_DATATYPE_COLOR: return "color";
|
||||
case PAR_ATTR_DATATYPE_MATRIX: return "matrix";
|
||||
case PAR_ATTR_DATATYPE_POINTER: return "pointer";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
static size_t nparticle_elem_bytes(int datatype)
|
||||
{
|
||||
switch (datatype) {
|
||||
case PAR_ATTR_DATATYPE_FLOAT: return sizeof(float);
|
||||
case PAR_ATTR_DATATYPE_INT: return sizeof(int);
|
||||
case PAR_ATTR_DATATYPE_BOOL: return sizeof(bool);
|
||||
case PAR_ATTR_DATATYPE_VECTOR:
|
||||
case PAR_ATTR_DATATYPE_POINT:
|
||||
case PAR_ATTR_DATATYPE_NORMAL:
|
||||
return sizeof(float)*3;
|
||||
case PAR_ATTR_DATATYPE_QUATERNION: return sizeof(float)*4;
|
||||
case PAR_ATTR_DATATYPE_COLOR: return sizeof(float)*4;
|
||||
case PAR_ATTR_DATATYPE_MATRIX: return sizeof(float)*16;
|
||||
case PAR_ATTR_DATATYPE_POINTER: return sizeof(void*);
|
||||
|
||||
default:
|
||||
BLI_assert(false); /* unknown datatype, should never happen */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void nparticle_attribute_state_init(NParticleAttribute *attr, NParticleAttributeState *attrstate)
|
||||
{
|
||||
attrstate->desc = attr->desc;
|
||||
attrstate->hashkey = BLI_ghashutil_strhash(attr->desc.name);
|
||||
BLI_pbuf_init(&attrstate->data, PAGE_BYTES, nparticle_elem_bytes(attr->desc.datatype));
|
||||
}
|
||||
|
||||
static void nparticle_attribute_state_free(NParticleAttributeState *state)
|
||||
{
|
||||
BLI_pbuf_free(&state->data);
|
||||
}
|
||||
|
||||
static void nparticle_attribute_state_copy(NParticleAttributeState *to, NParticleAttributeState *from)
|
||||
{
|
||||
to->desc = from->desc;
|
||||
to->hashkey = from->hashkey;
|
||||
BLI_pbuf_copy(&to->data, &from->data);
|
||||
}
|
||||
|
||||
|
||||
static NParticleAttributeState *nparticle_state_add_attribute(NParticleState *state, NParticleAttribute *attr)
|
||||
{
|
||||
NParticleAttributeState *attrstate = MEM_callocN(sizeof(NParticleAttributeState), "particle attribute state");
|
||||
nparticle_attribute_state_init(attr, attrstate);
|
||||
BLI_addtail(&state->attributes, attrstate);
|
||||
return attrstate;
|
||||
}
|
||||
|
||||
static void nparticle_state_remove_attribute(NParticleState *state, const char *name)
|
||||
{
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(state, name);
|
||||
if (attrstate) {
|
||||
BLI_remlink(&state->attributes, attrstate);
|
||||
nparticle_attribute_state_free(attrstate);
|
||||
MEM_freeN(attrstate);
|
||||
}
|
||||
}
|
||||
|
||||
static void nparticle_state_clear(NParticleState *state)
|
||||
{
|
||||
NParticleAttributeState *attrstate;
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next)
|
||||
nparticle_attribute_state_free(attrstate);
|
||||
BLI_freelistN(&state->attributes);
|
||||
}
|
||||
|
||||
static void nparticle_system_sync_state_attributes(NParticleSystem *psys, NParticleState *state)
|
||||
{
|
||||
NParticleAttribute *attr;
|
||||
NParticleAttributeState *attrstate, *attrstate_next;
|
||||
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next)
|
||||
attrstate->flag &= ~PAR_ATTR_STATE_TEST;
|
||||
for (attr = psys->attributes.first; attr; attr = attr->next) {
|
||||
attrstate = BKE_nparticle_state_find_attribute(state, attr->desc.name);
|
||||
|
||||
/* add missing attributes */
|
||||
if (!attrstate) {
|
||||
attrstate = nparticle_state_add_attribute(state, attr);
|
||||
}
|
||||
|
||||
attrstate->flag |= PAR_ATTR_STATE_TEST;
|
||||
}
|
||||
|
||||
/* remove unused attribute states */
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate_next) {
|
||||
attrstate_next = attrstate->next;
|
||||
|
||||
if (!(attrstate->flag & PAR_ATTR_STATE_TEST)) {
|
||||
BLI_remlink(&state->attributes, attrstate);
|
||||
nparticle_attribute_state_free(attrstate);
|
||||
MEM_freeN(attrstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void nparticle_system_default_attributes(NParticleSystem *psys)
|
||||
{
|
||||
/* required attributes */
|
||||
BKE_nparticle_attribute_new(psys, "id", PAR_ATTR_DATATYPE_INT, PAR_ATTR_REQUIRED | PAR_ATTR_READONLY);
|
||||
|
||||
/* common attributes */
|
||||
BKE_nparticle_attribute_new(psys, "position", PAR_ATTR_DATATYPE_POINT, PAR_ATTR_PROTECTED);
|
||||
BKE_nparticle_attribute_new(psys, "rotation", PAR_ATTR_DATATYPE_QUATERNION, PAR_ATTR_PROTECTED);
|
||||
|
||||
/* XXX bullet RB pointers, this should be based on actual simulation settings and requirements */
|
||||
BKE_nparticle_attribute_new(psys, "rigid_body", PAR_ATTR_DATATYPE_POINTER, PAR_ATTR_PROTECTED | PAR_ATTR_TEMPORARY);
|
||||
}
|
||||
|
||||
NParticleSystem *BKE_nparticle_system_new(void)
|
||||
{
|
||||
NParticleSystem *psys = MEM_callocN(sizeof(NParticleSystem), "nparticle system");
|
||||
|
||||
nparticle_system_default_attributes(psys);
|
||||
|
||||
psys->state = BKE_nparticle_state_new(psys);
|
||||
|
||||
return psys;
|
||||
}
|
||||
|
||||
void BKE_nparticle_system_free(NParticleSystem *psys)
|
||||
{
|
||||
NParticleDisplay *display, *display_next;
|
||||
|
||||
BKE_nparticle_attribute_remove_all(psys);
|
||||
|
||||
BKE_nparticle_state_free(psys->state);
|
||||
|
||||
for (display = psys->display.first; display; display = display_next) {
|
||||
display_next = display->next;
|
||||
BKE_nparticle_display_free(psys, display);
|
||||
}
|
||||
|
||||
MEM_freeN(psys);
|
||||
}
|
||||
|
||||
NParticleSystem *BKE_nparticle_system_copy(NParticleSystem *psys)
|
||||
{
|
||||
NParticleSystem *npsys = MEM_dupallocN(psys);
|
||||
NParticleAttribute *attr, *nattr;
|
||||
NParticleDisplay *display;
|
||||
|
||||
npsys->attributes.first = npsys->attributes.last = NULL;
|
||||
for (attr = psys->attributes.first; attr; attr = attr->next) {
|
||||
nattr = BKE_nparticle_attribute_copy(npsys, psys, attr);
|
||||
}
|
||||
|
||||
if (psys->state)
|
||||
npsys->state = BKE_nparticle_state_copy(psys->state);
|
||||
|
||||
npsys->display.first = npsys->display.last = NULL;
|
||||
for (display = psys->display.first; display; display = display->next) {
|
||||
BKE_nparticle_display_copy(npsys, display);
|
||||
}
|
||||
|
||||
return npsys;
|
||||
}
|
||||
|
||||
void BKE_nparticle_system_set_state(NParticleSystem *psys, NParticleState *state)
|
||||
{
|
||||
if (state) {
|
||||
if (psys->state)
|
||||
BKE_nparticle_state_free(psys->state);
|
||||
|
||||
psys->state = BKE_nparticle_state_copy(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NParticleState *BKE_nparticle_state_new(NParticleSystem *psys)
|
||||
{
|
||||
NParticleState *state = MEM_callocN(sizeof(NParticleState), "particle state");
|
||||
|
||||
nparticle_system_sync_state_attributes(psys, state);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
NParticleState *BKE_nparticle_state_copy(NParticleState *state)
|
||||
{
|
||||
NParticleState *nstate = MEM_dupallocN(state);
|
||||
NParticleAttributeState *attrstate, *nattrstate;
|
||||
|
||||
BLI_duplicatelist(&state->attributes, &nstate->attributes);
|
||||
|
||||
for (attrstate = state->attributes.first, nattrstate = nstate->attributes.first;
|
||||
attrstate;
|
||||
attrstate = attrstate->next, nattrstate = nattrstate->next)
|
||||
nparticle_attribute_state_copy(nattrstate, attrstate);
|
||||
|
||||
nstate->py_handle = NULL;
|
||||
|
||||
return nstate;
|
||||
}
|
||||
|
||||
void BKE_nparticle_state_free(NParticleState *state)
|
||||
{
|
||||
NParticleAttributeState *attrstate;
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next)
|
||||
nparticle_attribute_state_free(attrstate);
|
||||
BLI_freelistN(&state->attributes);
|
||||
MEM_freeN(state);
|
||||
}
|
||||
|
||||
|
||||
void BKE_nparticle_state_attributes_begin(NParticleState *state, NParticleAttributeStateIterator *iter)
|
||||
{
|
||||
iter->attrstate = state->attributes.first;
|
||||
}
|
||||
|
||||
bool BKE_nparticle_state_attribute_iter_valid(NParticleAttributeStateIterator *iter)
|
||||
{
|
||||
return (iter->attrstate != NULL);
|
||||
}
|
||||
|
||||
void BKE_nparticle_state_attribute_iter_next(NParticleAttributeStateIterator *iter)
|
||||
{
|
||||
iter->attrstate = iter->attrstate->next;
|
||||
}
|
||||
|
||||
void BKE_nparticle_state_attribute_iter_end(NParticleAttributeStateIterator *iter)
|
||||
{
|
||||
iter->attrstate = NULL;
|
||||
}
|
||||
|
||||
|
||||
NParticleAttribute *BKE_nparticle_attribute_find(NParticleSystem *psys, const char *name)
|
||||
{
|
||||
NParticleAttribute *attr;
|
||||
for (attr = psys->attributes.first; attr; attr = attr->next)
|
||||
if (STREQ(attr->desc.name, name))
|
||||
return attr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NParticleAttribute *BKE_nparticle_attribute_new(NParticleSystem *psys, const char *name, int datatype, int flag)
|
||||
{
|
||||
NParticleAttribute *attr;
|
||||
|
||||
attr = BKE_nparticle_attribute_find(psys, name);
|
||||
if (attr) {
|
||||
/* if attribute with the same name exists, remove it first */
|
||||
BKE_nparticle_attribute_remove(psys, attr);
|
||||
}
|
||||
|
||||
attr = MEM_callocN(sizeof(NParticleAttribute), "particle system attribute");
|
||||
BLI_strncpy(attr->desc.name, name, sizeof(attr->desc.name));
|
||||
attr->desc.datatype = datatype;
|
||||
attr->desc.flag = flag;
|
||||
/* some data types should have more usable defaults
|
||||
* without explicitly setting them.
|
||||
*/
|
||||
switch (datatype) {
|
||||
case PAR_ATTR_DATATYPE_NORMAL:
|
||||
((float*)attr->desc.default_value)[2] = 1.0f;
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_QUATERNION:
|
||||
unit_qt((float*)attr->desc.default_value);
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_COLOR:
|
||||
((float*)attr->desc.default_value)[3] = 1.0f;
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_MATRIX:
|
||||
unit_m4((float(*)[4])attr->desc.default_value);
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_addtail(&psys->attributes, attr);
|
||||
|
||||
if (psys->state)
|
||||
nparticle_state_add_attribute(psys->state, attr);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
void BKE_nparticle_attribute_remove(NParticleSystem *psys, NParticleAttribute *attr)
|
||||
{
|
||||
if (psys->state)
|
||||
nparticle_state_remove_attribute(psys->state, attr->desc.name);
|
||||
|
||||
BLI_remlink(&psys->attributes, attr);
|
||||
MEM_freeN(attr);
|
||||
}
|
||||
|
||||
void BKE_nparticle_attribute_remove_all(NParticleSystem *psys)
|
||||
{
|
||||
NParticleAttribute *attr, *attr_next;
|
||||
|
||||
if (psys->state)
|
||||
nparticle_state_clear(psys->state);
|
||||
|
||||
for (attr = psys->attributes.first; attr; attr = attr_next) {
|
||||
attr_next = attr->next;
|
||||
MEM_freeN(attr);
|
||||
}
|
||||
psys->attributes.first = psys->attributes.last = NULL;
|
||||
}
|
||||
|
||||
NParticleAttribute *BKE_nparticle_attribute_copy(NParticleSystem *to_psys, NParticleSystem *UNUSED(from_psys), NParticleAttribute *from_attr)
|
||||
{
|
||||
NParticleAttribute *to_attr = MEM_dupallocN(from_attr);
|
||||
BLI_addtail(&to_psys->attributes, to_attr);
|
||||
|
||||
if (to_psys->state)
|
||||
nparticle_state_add_attribute(to_psys->state, to_attr);
|
||||
|
||||
return to_attr;
|
||||
}
|
||||
|
||||
void BKE_nparticle_attribute_move(NParticleSystem *psys, int from_index, int to_index)
|
||||
{
|
||||
NParticleAttribute *attr;
|
||||
|
||||
if (from_index == to_index)
|
||||
return;
|
||||
if (from_index < 0 || to_index < 0)
|
||||
return;
|
||||
|
||||
attr = BLI_findlink(&psys->attributes, from_index);
|
||||
if (to_index < from_index) {
|
||||
NParticleAttribute *nextattr = BLI_findlink(&psys->attributes, to_index);
|
||||
if (nextattr) {
|
||||
BLI_remlink(&psys->attributes, attr);
|
||||
BLI_insertlinkbefore(&psys->attributes, nextattr, attr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
NParticleAttribute *prevattr = BLI_findlink(&psys->attributes, to_index);
|
||||
if (prevattr) {
|
||||
BLI_remlink(&psys->attributes, attr);
|
||||
BLI_insertlinkafter(&psys->attributes, prevattr, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BKE_nparticle_state_num_attributes(NParticleState *state)
|
||||
{
|
||||
return BLI_countlist(&state->attributes);
|
||||
}
|
||||
|
||||
NParticleAttributeState *BKE_nparticle_state_find_attribute(NParticleState *state, const char *name)
|
||||
{
|
||||
int hashkey = BLI_ghashutil_strhash(name);
|
||||
NParticleAttributeState *attrstate;
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next)
|
||||
if (attrstate->hashkey == hashkey)
|
||||
return attrstate;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE NParticleAttributeState *nparticle_state_find_attribute_id(NParticleState *state)
|
||||
{
|
||||
return BKE_nparticle_state_find_attribute(state, "id");
|
||||
}
|
||||
|
||||
NParticleAttributeState *BKE_nparticle_state_get_attribute_by_index(NParticleState *state, int index)
|
||||
{
|
||||
return BLI_findlink(&state->attributes, index);
|
||||
}
|
||||
|
||||
int BKE_nparticle_state_num_particles(NParticleState *state)
|
||||
{
|
||||
NParticleAttributeState *attrstate = nparticle_state_find_attribute_id(state);
|
||||
return attrstate ? attrstate->data.totelem : 0;
|
||||
}
|
||||
|
||||
void *BKE_nparticle_attribute_state_data(NParticleAttributeState *attrstate, int index)
|
||||
{
|
||||
return BLI_pbuf_get(&attrstate->data, index);
|
||||
}
|
||||
|
||||
|
||||
int BKE_nparticle_find_index(NParticleState *state, NParticleID id)
|
||||
{
|
||||
NParticleAttributeState *attrstate = nparticle_state_find_attribute_id(state);
|
||||
if (attrstate) {
|
||||
bPagedBuffer *pbuf = &attrstate->data;
|
||||
bPagedBufferIterator it;
|
||||
|
||||
for (BLI_pbuf_iter_init(pbuf, &it); BLI_pbuf_iter_valid(pbuf, &it); BLI_pbuf_iter_next(pbuf, &it)) {
|
||||
if (*(int*)it.data == id)
|
||||
return it.index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool BKE_nparticle_exists(NParticleState *state, NParticleID id)
|
||||
{
|
||||
return BKE_nparticle_find_index(state, id) >= 0;
|
||||
}
|
||||
|
||||
static bool nparticle_attribute_is_id(NParticleAttributeDescription *desc)
|
||||
{
|
||||
return STREQ(desc->name, "id");
|
||||
}
|
||||
|
||||
int BKE_nparticle_add(NParticleState *state, NParticleID id)
|
||||
{
|
||||
int index = BKE_nparticle_find_index(state, id);
|
||||
if (index < 0) {
|
||||
NParticleAttributeState *attrstate;
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next) {
|
||||
BLI_pbuf_add_elements(&attrstate->data, 1);
|
||||
index = attrstate->data.totelem - 1;
|
||||
|
||||
if (nparticle_attribute_is_id(&attrstate->desc)) {
|
||||
*(int*)BLI_pbuf_get(&attrstate->data, index) = (int)id;
|
||||
}
|
||||
else {
|
||||
memcpy(BLI_pbuf_get(&attrstate->data, index), attrstate->desc.default_value, attrstate->data.elem_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void BKE_nparticle_remove(NParticleState *state, NParticleID id)
|
||||
{
|
||||
int index = BKE_nparticle_find_index(state, id);
|
||||
if (index >= 0) {
|
||||
NParticleAttributeState *attrstate;
|
||||
for (attrstate = state->attributes.first; attrstate; attrstate = attrstate->next) {
|
||||
/* XXX TODO paged buffer doesn't support removing yet */
|
||||
// BLI_pbuf_remove_elements(&attrstate->data, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BKE_nparticle_iter_init(NParticleState *state, NParticleIterator *it)
|
||||
{
|
||||
it->state = state;
|
||||
it->index = 0;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_from_id(NParticleState *state, NParticleIterator *it, NParticleID id)
|
||||
{
|
||||
it->state = state;
|
||||
it->index = BKE_nparticle_find_index(state, id);
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_from_index(NParticleState *state, NParticleIterator *it, int index)
|
||||
{
|
||||
NParticleAttributeState *attrstate = nparticle_state_find_attribute_id(state);
|
||||
it->state = state;
|
||||
if (index >= 0 && attrstate && index < attrstate->data.totelem)
|
||||
it->index = index;
|
||||
else
|
||||
it->index = -1;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_next(NParticleIterator *it)
|
||||
{
|
||||
++it->index;
|
||||
}
|
||||
|
||||
bool BKE_nparticle_iter_valid(NParticleIterator *it)
|
||||
{
|
||||
NParticleAttributeState *attrstate = nparticle_state_find_attribute_id(it->state);
|
||||
if (attrstate)
|
||||
return it->index >= 0 && it->index < attrstate->data.totelem;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
BLI_INLINE void *nparticle_data_ptr(NParticleState *state, const char *name, int index)
|
||||
{
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(state, name);
|
||||
if (attrstate)
|
||||
return BLI_pbuf_get(&attrstate->data, index);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE bool nparticle_check_attribute_type(NParticleState *state, const char *name, eParticleAttributeDataType datatype)
|
||||
{
|
||||
/* sanity check to ensure the retrieved data attribute has the correct type.
|
||||
* only happens in debug, no overhead created for release builds.
|
||||
*/
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(state, name);
|
||||
return !attrstate || attrstate->desc.datatype == datatype;
|
||||
}
|
||||
|
||||
#if 0 /* unused */
|
||||
void *BKE_nparticle_iter_get_data(struct NParticleIterator *it, const char *attr)
|
||||
{
|
||||
return nparticle_data_ptr(it->state, attr, it->index);
|
||||
}
|
||||
#endif
|
||||
|
||||
int BKE_nparticle_iter_get_int(NParticleIterator *it, const char *attr)
|
||||
{
|
||||
int *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_INT));
|
||||
return data ? *data : 0;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_set_int(NParticleIterator *it, const char *attr, int value)
|
||||
{
|
||||
int *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_INT));
|
||||
if (data)
|
||||
*data = value;
|
||||
}
|
||||
|
||||
float BKE_nparticle_iter_get_float(NParticleIterator *it, const char *attr)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_FLOAT));
|
||||
return data ? *data : 0.0f;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_set_float(NParticleIterator *it, const char *attr, float value)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_FLOAT));
|
||||
if (data)
|
||||
*data = value;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_get_vector(NParticleIterator *it, const char *attr, float *result)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_VECTOR)
|
||||
|| nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_POINT)
|
||||
|| nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_NORMAL));
|
||||
if (data)
|
||||
copy_v3_v3(result, data);
|
||||
else
|
||||
zero_v3(result);
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_set_vector(NParticleIterator *it, const char *attr, const float *value)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_VECTOR)
|
||||
|| nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_POINT)
|
||||
|| nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_NORMAL));
|
||||
if (data)
|
||||
copy_v3_v3(data, value);
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_get_quaternion(NParticleIterator *it, const char *attr, float *result)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_QUATERNION));
|
||||
if (data)
|
||||
copy_qt_qt(result, data);
|
||||
else
|
||||
unit_qt(result);
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_set_quaternion(NParticleIterator *it, const char *attr, const float *value)
|
||||
{
|
||||
float *data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_QUATERNION));
|
||||
if (data)
|
||||
copy_qt_qt(data, value);
|
||||
}
|
||||
|
||||
void *BKE_nparticle_iter_get_pointer(NParticleIterator *it, const char *attr)
|
||||
{
|
||||
void **data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_POINTER));
|
||||
return data ? *data : NULL;
|
||||
}
|
||||
|
||||
void BKE_nparticle_iter_set_pointer(NParticleIterator *it, const char *attr, void *value)
|
||||
{
|
||||
void **data = nparticle_data_ptr(it->state, attr, it->index);
|
||||
BLI_assert(nparticle_check_attribute_type(it->state, attr, PAR_ATTR_DATATYPE_POINTER));
|
||||
if (data)
|
||||
*data = value;
|
||||
}
|
||||
|
||||
|
||||
NParticleDisplay *BKE_nparticle_display_add(NParticleSystem *psys, int type)
|
||||
{
|
||||
NParticleDisplay *display = MEM_callocN(sizeof(NParticleDisplay), "particle display");
|
||||
display->type = type;
|
||||
|
||||
switch (type) {
|
||||
case PAR_DISPLAY_PARTICLE:
|
||||
BLI_strncpy(display->attribute, "position", sizeof(display->attribute));
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_addtail(&psys->display, display);
|
||||
return display;
|
||||
}
|
||||
|
||||
NParticleDisplay *BKE_nparticle_display_copy(NParticleSystem *psys, NParticleDisplay *display)
|
||||
{
|
||||
NParticleDisplay *ndisplay = MEM_dupallocN(display);
|
||||
|
||||
BLI_addtail(&psys->display, display);
|
||||
return ndisplay;
|
||||
}
|
||||
|
||||
void BKE_nparticle_display_free(NParticleSystem *psys, NParticleDisplay *display)
|
||||
{
|
||||
BLI_remlink(&psys->display, display);
|
||||
|
||||
switch (display->type) {
|
||||
case PAR_DISPLAY_DUPLI: {
|
||||
NParticleDisplayDupliObject *dob, *dob_next;
|
||||
for (dob = display->dupli_objects.first; dob; dob = dob_next) {
|
||||
dob_next = dob->next;
|
||||
MEM_freeN(dob);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(display);
|
||||
}
|
||||
|
||||
void BKE_nparticle_update_object_dupli_flags(Object *ob, NParticleSystem *psys)
|
||||
{
|
||||
NParticleDisplay *display;
|
||||
ob->transflag &= ~OB_DUPLI_NPARTICLE;
|
||||
for (display = psys->display.first; display; display = display->next) {
|
||||
if (display->type == PAR_DISPLAY_DUPLI)
|
||||
ob->transflag |= OB_DUPLI_NPARTICLE;
|
||||
}
|
||||
}
|
||||
|
||||
NParticleDisplayDupliObject *BKE_nparticle_display_dupli_object_add(NParticleDisplay *display)
|
||||
{
|
||||
NParticleDisplayDupliObject *dob;
|
||||
|
||||
BLI_assert(display->type == PAR_DISPLAY_DUPLI);
|
||||
|
||||
dob = MEM_callocN(sizeof(NParticleDisplayDupliObject), "particle dupli object");
|
||||
BLI_addtail(&display->dupli_objects, dob);
|
||||
return dob;
|
||||
}
|
||||
|
||||
void BKE_nparticle_display_dupli_object_remove(NParticleDisplay *display, NParticleDisplayDupliObject *dupli_object)
|
||||
{
|
||||
BLI_assert(display->type == PAR_DISPLAY_DUPLI);
|
||||
|
||||
BLI_remlink(&display->dupli_objects, dupli_object);
|
||||
MEM_freeN(dupli_object);
|
||||
}
|
||||
|
||||
void BKE_nparticle_display_dupli_object_remove_all(NParticleDisplay *display)
|
||||
{
|
||||
NParticleDisplayDupliObject *dob, *dob_next;
|
||||
|
||||
BLI_assert(display->type == PAR_DISPLAY_DUPLI);
|
||||
|
||||
for (dob = display->dupli_objects.first; dob; dob = dob_next) {
|
||||
dob_next = dob->next;
|
||||
|
||||
MEM_freeN(dob);
|
||||
}
|
||||
display->dupli_objects.first = display->dupli_objects.last = NULL;
|
||||
}
|
||||
|
||||
void BKE_nparticle_display_dupli_object_move(NParticleDisplay *display, int from_index, int to_index)
|
||||
{
|
||||
NParticleDisplayDupliObject *dob;
|
||||
|
||||
BLI_assert(display->type == PAR_DISPLAY_DUPLI);
|
||||
|
||||
if (from_index == to_index)
|
||||
return;
|
||||
if (from_index < 0 || to_index < 0)
|
||||
return;
|
||||
|
||||
dob = BLI_findlink(&display->dupli_objects, from_index);
|
||||
if (to_index < from_index) {
|
||||
NParticleDisplayDupliObject *nextdob = BLI_findlink(&display->dupli_objects, to_index);
|
||||
if (nextdob) {
|
||||
BLI_remlink(&display->dupli_objects, dob);
|
||||
BLI_insertlinkbefore(&display->dupli_objects, nextdob, dob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
NParticleDisplayDupliObject *prevdob = BLI_findlink(&display->dupli_objects, to_index);
|
||||
if (prevdob) {
|
||||
BLI_remlink(&display->dupli_objects, dob);
|
||||
BLI_insertlinkafter(&display->dupli_objects, prevdob, dob);
|
||||
}
|
||||
}
|
||||
}
|
@@ -95,6 +95,7 @@
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_mball.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nparticle.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -2333,7 +2334,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
|
||||
/* try to fall back to the scene rigid body world if none given */
|
||||
rbw = rbw ? rbw : scene->rigidbody_world;
|
||||
/* read values pushed into RBO from sim/cache... */
|
||||
BKE_rigidbody_sync_transforms(rbw, ob, ctime);
|
||||
BKE_rigidbody_object_apply_transforms(rbw, ob, ctime);
|
||||
|
||||
/* solve constraints */
|
||||
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
|
||||
@@ -2885,6 +2886,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
|
||||
AnimData *adt = BKE_animdata_from_id(data_id);
|
||||
Key *key;
|
||||
float ctime = BKE_scene_frame_get(scene);
|
||||
ModifierData *md;
|
||||
|
||||
if (G.debug & G_DEBUG_DEPSGRAPH)
|
||||
printf("recalcdata %s\n", ob->id.name + 2);
|
||||
@@ -3020,7 +3022,15 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
|
||||
psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* nparticles */
|
||||
for (md = ob->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_NParticleSystem) {
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData*)md;
|
||||
BKE_nparticle_update_object_dupli_flags(ob, pmd->psys);
|
||||
}
|
||||
}
|
||||
|
||||
/* quick cache removed */
|
||||
}
|
||||
|
||||
|
@@ -44,6 +44,9 @@
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_vfont_types.h"
|
||||
|
||||
@@ -56,6 +59,7 @@
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_nparticle.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_scene.h"
|
||||
@@ -1139,6 +1143,66 @@ const DupliGenerator gen_dupli_particles = {
|
||||
|
||||
/* ------------- */
|
||||
|
||||
/* OB_DUPLIPARTS */
|
||||
static void make_duplis_nparticle_system(const DupliContext *ctx, NParticleSystem *psys, NParticleDisplay *display)
|
||||
{
|
||||
NParticleIterator iter;
|
||||
NParticleDisplayDupliObject *dupli, *dob;
|
||||
int totdupli, i;
|
||||
float loc[3], rot[4], scale[3], obmat[4][4];
|
||||
|
||||
/* for faster index-based lookup make a temp array */
|
||||
totdupli = BLI_countlist(&display->dupli_objects);
|
||||
dupli = MEM_mallocN((unsigned int)totdupli * sizeof(NParticleDisplayDupliObject), "dupli objects");
|
||||
for (dob = display->dupli_objects.first, i = 0; dob; dob = dob->next, ++i)
|
||||
memcpy(&dupli[i], dob, sizeof(NParticleDisplayDupliObject));
|
||||
|
||||
scale[0] = scale[1] = scale[2] = 1.0f;
|
||||
|
||||
for (BKE_nparticle_iter_init(psys->state, &iter); BKE_nparticle_iter_valid(&iter); BKE_nparticle_iter_next(&iter)) {
|
||||
i = BKE_nparticle_iter_get_int(&iter, "dupli");
|
||||
if (i < 0 || i >= totdupli || dupli[i].object==NULL)
|
||||
continue;
|
||||
|
||||
BKE_nparticle_iter_get_vector(&iter, "position", loc);
|
||||
BKE_nparticle_iter_get_quaternion(&iter, "rotation", rot);
|
||||
loc_quat_size_to_mat4(obmat, loc, rot, scale);
|
||||
|
||||
make_dupli(ctx, dupli[i].object, obmat, (int)BKE_nparticle_iter_get_id(&iter), false, false);
|
||||
}
|
||||
|
||||
MEM_freeN(dupli);
|
||||
}
|
||||
|
||||
static void make_duplis_nparticles(const DupliContext *ctx)
|
||||
{
|
||||
ModifierData *md;
|
||||
int pmd_index = 0; /* XXX not really a persistent index, but modifier is only stop-gap design anyway */
|
||||
for (md = ctx->object->modifiers.first; md; md = md->next) {
|
||||
if (md->type == eModifierType_NParticleSystem) {
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData *)md;
|
||||
NParticleDisplay *display;
|
||||
/* particles create one more level for persistent psys index */
|
||||
DupliContext pctx;
|
||||
copy_dupli_context(&pctx, ctx, ctx->object, NULL, pmd_index, false);
|
||||
|
||||
for (display = pmd->psys->display.first; display; display = display->next) {
|
||||
if (display->type == PAR_DISPLAY_DUPLI)
|
||||
make_duplis_nparticle_system(&pctx, pmd->psys, display);
|
||||
}
|
||||
|
||||
++pmd_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DupliGenerator gen_dupli_nparticles = {
|
||||
OB_DUPLI_NPARTICLE, /* type */
|
||||
make_duplis_nparticles /* make_duplis */
|
||||
};
|
||||
|
||||
/* ------------- */
|
||||
|
||||
/* select dupli generator from given context */
|
||||
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
||||
{
|
||||
@@ -1155,6 +1219,9 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
||||
if (transflag & OB_DUPLIPARTS) {
|
||||
return &gen_dupli_particles;
|
||||
}
|
||||
else if (transflag & OB_DUPLI_NPARTICLE) {
|
||||
return &gen_dupli_nparticles;
|
||||
}
|
||||
else if (transflag & OB_DUPLIVERTS) {
|
||||
if (ctx->object->type == OB_MESH) {
|
||||
return &gen_dupli_verts;
|
||||
|
File diff suppressed because it is too large
Load Diff
863
source/blender/blenkernel/intern/rigidbody_objects.c
Normal file
863
source/blender/blenkernel/intern/rigidbody_objects.c
Normal file
@@ -0,0 +1,863 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 Blender Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Joshua Leung, Sergej Reich, Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file rigidbody_objects.c
|
||||
* \ingroup blenkernel
|
||||
* \brief Rigid body object simulation
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#ifdef WITH_BULLET
|
||||
# include "RBI_api.h"
|
||||
#endif
|
||||
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_cdderivedmesh.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_rigidbody.h"
|
||||
|
||||
/* ------------------------ */
|
||||
/* Main Simulation Sync */
|
||||
|
||||
static void rigidbody_sync_object(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
|
||||
{
|
||||
float loc[3];
|
||||
float rot[4];
|
||||
float scale[3];
|
||||
|
||||
/* only update if rigid body exists */
|
||||
if (rbo->physics_object == NULL)
|
||||
return;
|
||||
|
||||
if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) {
|
||||
DerivedMesh *dm = ob->derivedDeform;
|
||||
if (dm) {
|
||||
MVert *mvert = dm->getVertArray(dm);
|
||||
int totvert = dm->getNumVerts(dm);
|
||||
BoundBox *bb = BKE_object_boundbox_get(ob);
|
||||
|
||||
RB_shape_trimesh_update(rbo->physics_shape, (float *)mvert, totvert, sizeof(MVert), bb->vec[0], bb->vec[6]);
|
||||
}
|
||||
}
|
||||
|
||||
mat4_decompose(loc, rot, scale, ob->obmat);
|
||||
|
||||
/* update scale for all objects */
|
||||
RB_body_set_scale(rbo->physics_object, scale);
|
||||
/* compensate for embedded convex hull collision margin */
|
||||
if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH)
|
||||
RB_shape_set_margin(rbo->physics_shape, BKE_rigidbody_object_margin(rbo) * MIN3(scale[0], scale[1], scale[2]));
|
||||
|
||||
/* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */
|
||||
if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
|
||||
RB_body_set_kinematic_state(rbo->physics_object, true);
|
||||
RB_body_set_mass(rbo->physics_object, 0.0f);
|
||||
}
|
||||
|
||||
/* update rigid body location and rotation for kinematic bodies */
|
||||
if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
|
||||
RB_body_activate(rbo->physics_object);
|
||||
RB_body_set_loc_rot(rbo->physics_object, loc, rot);
|
||||
}
|
||||
/* update influence of effectors - but don't do it on an effector */
|
||||
/* only dynamic bodies need effector update */
|
||||
else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) {
|
||||
EffectorWeights *effector_weights = rbw->effector_weights;
|
||||
EffectedPoint epoint;
|
||||
ListBase *effectors;
|
||||
|
||||
/* get effectors present in the group specified by effector_weights */
|
||||
effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
|
||||
if (effectors) {
|
||||
float eff_force[3] = {0.0f, 0.0f, 0.0f};
|
||||
float eff_loc[3], eff_vel[3];
|
||||
|
||||
/* create dummy 'point' which represents last known position of object as result of sim */
|
||||
// XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
|
||||
RB_body_get_position(rbo->physics_object, eff_loc);
|
||||
RB_body_get_linear_velocity(rbo->physics_object, eff_vel);
|
||||
|
||||
pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
|
||||
|
||||
/* calculate net force of effectors, and apply to sim object
|
||||
* - we use 'central force' since apply force requires a "relative position" which we don't have...
|
||||
*/
|
||||
pdDoEffectors(effectors, NULL, effector_weights, &epoint, eff_force, NULL);
|
||||
if (G.f & G_DEBUG)
|
||||
printf("\tapplying force (%f,%f,%f) to '%s'\n", eff_force[0], eff_force[1], eff_force[2], ob->id.name + 2);
|
||||
/* activate object in case it is deactivated */
|
||||
if (!is_zero_v3(eff_force))
|
||||
RB_body_activate(rbo->physics_object);
|
||||
RB_body_apply_central_force(rbo->physics_object, eff_force);
|
||||
}
|
||||
else if (G.f & G_DEBUG)
|
||||
printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
|
||||
|
||||
/* cleanup */
|
||||
pdEndEffectors(&effectors);
|
||||
}
|
||||
/* NOTE: passive objects don't need to be updated since they don't move */
|
||||
|
||||
/* NOTE: no other settings need to be explicitly updated here,
|
||||
* since RNA setters take care of the rest :)
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Create physics sim representation of object given RigidBody settings
|
||||
*
|
||||
* \param rebuild Even if an instance already exists, replace it
|
||||
*/
|
||||
static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rebuild)
|
||||
{
|
||||
RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
|
||||
rbRigidBody *body;
|
||||
float loc[3];
|
||||
float rot[4];
|
||||
|
||||
/* sanity checks:
|
||||
* - object doesn't have RigidBody info already: then why is it here?
|
||||
*/
|
||||
if (rbo == NULL)
|
||||
return;
|
||||
|
||||
/* make sure collision shape exists */
|
||||
/* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
|
||||
if (rbo->physics_shape == NULL || rebuild)
|
||||
BKE_rigidbody_validate_sim_shape(ob, true);
|
||||
|
||||
rbo->physics_object = BKE_rigidbody_body_ensure_alloc(rbw, rbo->physics_object, rebuild);
|
||||
body = rbo->physics_object; /* shortcut */
|
||||
|
||||
mat4_to_loc_quat(loc, rot, ob->obmat);
|
||||
RB_body_init(body, rbo->physics_shape, loc, rot);
|
||||
|
||||
RB_body_set_friction(body, rbo->friction);
|
||||
RB_body_set_restitution(body, rbo->restitution);
|
||||
|
||||
RB_body_set_damping(body, rbo->lin_damping, rbo->ang_damping);
|
||||
RB_body_set_sleep_thresh(body, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
|
||||
RB_body_set_activation_state(body, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
|
||||
|
||||
if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
|
||||
RB_body_deactivate(body);
|
||||
|
||||
|
||||
RB_body_set_linear_factor(body,
|
||||
(ob->protectflag & OB_LOCK_LOCX) == 0,
|
||||
(ob->protectflag & OB_LOCK_LOCY) == 0,
|
||||
(ob->protectflag & OB_LOCK_LOCZ) == 0);
|
||||
RB_body_set_angular_factor(body,
|
||||
(ob->protectflag & OB_LOCK_ROTX) == 0,
|
||||
(ob->protectflag & OB_LOCK_ROTY) == 0,
|
||||
(ob->protectflag & OB_LOCK_ROTZ) == 0);
|
||||
|
||||
RB_body_set_mass(body, BKE_rigidbody_object_mass(rbo));
|
||||
RB_body_set_kinematic_state(body, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
|
||||
|
||||
if (rbw && rbw->physics_world)
|
||||
RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
|
||||
}
|
||||
|
||||
void BKE_rigidbody_objects_build(Scene *scene, struct RigidBodyWorld *rbw, bool rebuild)
|
||||
{
|
||||
GroupObject *go;
|
||||
for (go = rbw->group->gobject.first; go; go = go->next) {
|
||||
Object *ob = go->ob;
|
||||
RigidBodyOb *rbo;
|
||||
|
||||
if (!ob || ob->type != OB_MESH)
|
||||
continue;
|
||||
|
||||
/* validate that we've got valid object set up here... */
|
||||
rbo = ob->rigidbody_object;
|
||||
/* update transformation matrix of the object so we don't get a frame of lag for simple animations */
|
||||
BKE_object_where_is_calc(scene, ob);
|
||||
|
||||
if (rbo == NULL) {
|
||||
/* Since this object is included in the sim group but doesn't have
|
||||
* rigid body settings (perhaps it was added manually), add!
|
||||
* - assume object to be active? That is the default for newly added settings...
|
||||
*/
|
||||
ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
|
||||
rigidbody_validate_sim_object(rbw, ob, true);
|
||||
|
||||
rbo = ob->rigidbody_object;
|
||||
}
|
||||
else {
|
||||
/* perform simulation data updates as tagged */
|
||||
/* refresh object... */
|
||||
if (rebuild) {
|
||||
/* World has been rebuilt so rebuild object */
|
||||
rigidbody_validate_sim_object(rbw, ob, true);
|
||||
}
|
||||
else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
|
||||
rigidbody_validate_sim_object(rbw, ob, false);
|
||||
}
|
||||
|
||||
/* refresh shape... */
|
||||
if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
|
||||
/* mesh/shape data changed, so force shape refresh */
|
||||
BKE_rigidbody_validate_sim_shape(ob, true);
|
||||
/* now tell RB sim about it */
|
||||
// XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies
|
||||
RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
|
||||
}
|
||||
|
||||
rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
|
||||
}
|
||||
|
||||
BKE_rigidbody_body_tag_used(rbo->physics_object);
|
||||
|
||||
/* update simulation object... */
|
||||
rigidbody_sync_object(scene, rbw, ob, rbo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create physics sim representation of constraint given rigid body constraint settings
|
||||
*
|
||||
* \param rebuild Even if an instance already exists, replace it
|
||||
*/
|
||||
static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, bool rebuild)
|
||||
{
|
||||
RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
|
||||
float loc[3];
|
||||
float rot[4];
|
||||
float lin_lower;
|
||||
float lin_upper;
|
||||
float ang_lower;
|
||||
float ang_upper;
|
||||
|
||||
/* sanity checks:
|
||||
* - object should have a rigid body constraint
|
||||
* - rigid body constraint should have at least one constrained object
|
||||
*/
|
||||
if (rbc == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
|
||||
if (rbc->physics_constraint) {
|
||||
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
|
||||
RB_constraint_delete(rbc->physics_constraint);
|
||||
rbc->physics_constraint = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rbc->physics_constraint && rebuild == false) {
|
||||
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
|
||||
}
|
||||
if (rbc->physics_constraint == NULL || rebuild) {
|
||||
rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object;
|
||||
rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object;
|
||||
|
||||
/* remove constraint if it already exists before creating a new one */
|
||||
if (rbc->physics_constraint) {
|
||||
RB_constraint_delete(rbc->physics_constraint);
|
||||
rbc->physics_constraint = NULL;
|
||||
}
|
||||
|
||||
mat4_to_loc_quat(loc, rot, ob->obmat);
|
||||
|
||||
if (rb1 && rb2) {
|
||||
switch (rbc->type) {
|
||||
case RBC_TYPE_POINT:
|
||||
rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2);
|
||||
break;
|
||||
case RBC_TYPE_FIXED:
|
||||
rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2);
|
||||
break;
|
||||
case RBC_TYPE_HINGE:
|
||||
rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2);
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
|
||||
RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
|
||||
}
|
||||
else
|
||||
RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f);
|
||||
break;
|
||||
case RBC_TYPE_SLIDER:
|
||||
rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2);
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
|
||||
RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
|
||||
else
|
||||
RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f);
|
||||
break;
|
||||
case RBC_TYPE_PISTON:
|
||||
rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2);
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
|
||||
lin_lower = rbc->limit_lin_x_lower;
|
||||
lin_upper = rbc->limit_lin_x_upper;
|
||||
}
|
||||
else {
|
||||
lin_lower = 0.0f;
|
||||
lin_upper = -1.0f;
|
||||
}
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
|
||||
ang_lower = rbc->limit_ang_x_lower;
|
||||
ang_upper = rbc->limit_ang_x_upper;
|
||||
}
|
||||
else {
|
||||
ang_lower = 0.0f;
|
||||
ang_upper = -1.0f;
|
||||
}
|
||||
RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper);
|
||||
break;
|
||||
case RBC_TYPE_6DOF_SPRING:
|
||||
rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2);
|
||||
|
||||
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X);
|
||||
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x);
|
||||
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x);
|
||||
|
||||
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y);
|
||||
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y);
|
||||
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y);
|
||||
|
||||
RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z);
|
||||
RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z);
|
||||
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z);
|
||||
|
||||
RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
|
||||
/* fall-through */
|
||||
case RBC_TYPE_6DOF:
|
||||
if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
|
||||
rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
|
||||
else
|
||||
RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
|
||||
break;
|
||||
case RBC_TYPE_MOTOR:
|
||||
rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
|
||||
|
||||
RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG);
|
||||
RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse);
|
||||
RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { /* can't create constraint without both rigid bodies */
|
||||
return;
|
||||
}
|
||||
|
||||
RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_USE_BREAKING)
|
||||
RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold);
|
||||
else
|
||||
RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX);
|
||||
|
||||
if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)
|
||||
RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations);
|
||||
else
|
||||
RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
|
||||
}
|
||||
|
||||
if (rbw && rbw->physics_world && rbc->physics_constraint) {
|
||||
RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_rigidbody_constraints_build(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
|
||||
{
|
||||
GroupObject *go;
|
||||
|
||||
if (!rbw->constraints)
|
||||
return;
|
||||
|
||||
for (go = rbw->constraints->gobject.first; go; go = go->next) {
|
||||
Object *ob = go->ob;
|
||||
|
||||
if (ob) {
|
||||
/* validate that we've got valid object set up here... */
|
||||
RigidBodyCon *rbc = ob->rigidbody_constraint;
|
||||
/* update transformation matrix of the object so we don't get a frame of lag for simple animations */
|
||||
BKE_object_where_is_calc(scene, ob);
|
||||
|
||||
if (rbc == NULL) {
|
||||
/* Since this object is included in the group but doesn't have
|
||||
* constraint settings (perhaps it was added manually), add!
|
||||
*/
|
||||
ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
|
||||
rigidbody_validate_sim_constraint(rbw, ob, true);
|
||||
|
||||
rbc = ob->rigidbody_constraint;
|
||||
}
|
||||
else {
|
||||
/* perform simulation data updates as tagged */
|
||||
if (rebuild) {
|
||||
/* World has been rebuilt so rebuild constraint */
|
||||
rigidbody_validate_sim_constraint(rbw, ob, true);
|
||||
}
|
||||
else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
|
||||
rigidbody_validate_sim_constraint(rbw, ob, false);
|
||||
}
|
||||
rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_rigidbody_constraints_apply(Scene *UNUSED(scene), RigidBodyWorld *UNUSED(rbw))
|
||||
{
|
||||
/* stub, just for consistency, might be useful later */
|
||||
}
|
||||
|
||||
/* ------------------------ */
|
||||
|
||||
static void rigidbody_world_apply_object(Scene *UNUSED(scene), Object *ob)
|
||||
{
|
||||
RigidBodyOb *rbo;
|
||||
|
||||
rbo = ob->rigidbody_object;
|
||||
/* reset kinematic state for transformed objects */
|
||||
if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) {
|
||||
RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
|
||||
RB_body_set_mass(rbo->physics_object, BKE_rigidbody_object_mass(rbo));
|
||||
/* deactivate passive objects so they don't interfere with deactivation of active objects */
|
||||
if (rbo->type == RBO_TYPE_PASSIVE)
|
||||
RB_body_deactivate(rbo->physics_object);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_rigidbody_objects_apply(Scene *scene, RigidBodyWorld *rbw)
|
||||
{
|
||||
GroupObject *go;
|
||||
|
||||
for (go = rbw->group->gobject.first; go; go = go->next) {
|
||||
Object *ob = go->ob;
|
||||
|
||||
if (!ob)
|
||||
continue;
|
||||
|
||||
rigidbody_world_apply_object(scene, ob);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------ */
|
||||
/* Transform Utils */
|
||||
|
||||
/* Sync rigid body and object transformations */
|
||||
void BKE_rigidbody_object_apply_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
|
||||
{
|
||||
RigidBodyOb *rbo = ob->rigidbody_object;
|
||||
|
||||
/* keep original transform for kinematic and passive objects */
|
||||
if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE)
|
||||
return;
|
||||
|
||||
/* use rigid body transform after cache start frame if objects is not being transformed */
|
||||
if (BKE_rigidbody_check_sim_running(rbw, ctime) && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
|
||||
float mat[4][4], size_mat[4][4], size[3];
|
||||
|
||||
normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point
|
||||
quat_to_mat4(mat, rbo->orn);
|
||||
copy_v3_v3(mat[3], rbo->pos);
|
||||
|
||||
mat4_to_size(size, ob->obmat);
|
||||
size_to_mat4(size_mat, size);
|
||||
mul_m4_m4m4(mat, mat, size_mat);
|
||||
|
||||
copy_m4_m4(ob->obmat, mat);
|
||||
}
|
||||
/* otherwise set rigid body transform to current obmat */
|
||||
else {
|
||||
mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
|
||||
}
|
||||
}
|
||||
|
||||
/* Used when canceling transforms - return rigidbody and object to initial states */
|
||||
void BKE_rigidbody_object_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
|
||||
{
|
||||
RigidBodyOb *rbo = ob->rigidbody_object;
|
||||
|
||||
/* return rigid body and object to their initial states */
|
||||
copy_v3_v3(rbo->pos, ob->loc);
|
||||
copy_v3_v3(ob->loc, loc);
|
||||
|
||||
if (ob->rotmode > 0) {
|
||||
eulO_to_quat(rbo->orn, ob->rot, ob->rotmode);
|
||||
copy_v3_v3(ob->rot, rot);
|
||||
}
|
||||
else if (ob->rotmode == ROT_MODE_AXISANGLE) {
|
||||
axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle);
|
||||
copy_v3_v3(ob->rotAxis, rotAxis);
|
||||
ob->rotAngle = rotAngle;
|
||||
}
|
||||
else {
|
||||
copy_qt_qt(rbo->orn, ob->quat);
|
||||
copy_qt_qt(ob->quat, quat);
|
||||
}
|
||||
if (rbo->physics_object) {
|
||||
/* allow passive objects to return to original transform */
|
||||
if (rbo->type == RBO_TYPE_PASSIVE)
|
||||
RB_body_set_kinematic_state(rbo->physics_object, true);
|
||||
RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn);
|
||||
}
|
||||
// RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
|
||||
}
|
||||
|
||||
/* ------------------------ */
|
||||
/* Object Data Management */
|
||||
|
||||
/* Add rigid body settings to the specified object */
|
||||
RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
|
||||
{
|
||||
RigidBodyOb *rbo;
|
||||
RigidBodyWorld *rbw = scene->rigidbody_world;
|
||||
|
||||
/* sanity checks
|
||||
* - rigidbody world must exist
|
||||
* - object must exist
|
||||
* - cannot add rigid body if it already exists
|
||||
*/
|
||||
if (ob == NULL || (ob->rigidbody_object != NULL))
|
||||
return NULL;
|
||||
|
||||
/* create new settings data, and link it up */
|
||||
rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
|
||||
|
||||
/* set default settings */
|
||||
rbo->type = type;
|
||||
|
||||
rbo->mass = 1.0f;
|
||||
|
||||
rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
|
||||
rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
|
||||
|
||||
rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
|
||||
|
||||
rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
|
||||
rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
|
||||
|
||||
rbo->lin_damping = 0.04f; /* 0.04 is game engine default */
|
||||
rbo->ang_damping = 0.1f; /* 0.1 is game engine default */
|
||||
|
||||
rbo->col_groups = 1;
|
||||
|
||||
/* use triangle meshes for passive objects
|
||||
* use convex hulls for active objects since dynamic triangle meshes are very unstable
|
||||
*/
|
||||
if (type == RBO_TYPE_ACTIVE)
|
||||
rbo->shape = RB_SHAPE_CONVEXH;
|
||||
else
|
||||
rbo->shape = RB_SHAPE_TRIMESH;
|
||||
|
||||
rbo->mesh_source = RBO_MESH_DEFORM;
|
||||
|
||||
/* set initial transform */
|
||||
mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
|
||||
|
||||
/* flag cache as outdated */
|
||||
BKE_rigidbody_cache_reset(rbw);
|
||||
|
||||
/* return this object */
|
||||
return rbo;
|
||||
}
|
||||
|
||||
void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
|
||||
{
|
||||
RigidBodyWorld *rbw = scene->rigidbody_world;
|
||||
RigidBodyOb *rbo = ob->rigidbody_object;
|
||||
RigidBodyCon *rbc;
|
||||
GroupObject *go;
|
||||
int i;
|
||||
|
||||
if (rbw) {
|
||||
/* remove from rigidbody world, free object won't do this */
|
||||
if (rbw->physics_world && rbo->physics_object)
|
||||
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
|
||||
|
||||
/* remove object from array */
|
||||
if (rbw && rbw->objects) {
|
||||
for (i = 0; i < rbw->numbodies; i++) {
|
||||
if (rbw->objects[i] == ob) {
|
||||
rbw->objects[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove object from rigid body constraints */
|
||||
if (rbw->constraints) {
|
||||
for (go = rbw->constraints->gobject.first; go; go = go->next) {
|
||||
Object *obt = go->ob;
|
||||
if (obt && obt->rigidbody_constraint) {
|
||||
rbc = obt->rigidbody_constraint;
|
||||
if (ELEM(ob, rbc->ob1, rbc->ob2)) {
|
||||
BKE_rigidbody_remove_constraint(scene, obt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove object's settings */
|
||||
BKE_rigidbody_free_object(ob);
|
||||
|
||||
/* flag cache as outdated */
|
||||
BKE_rigidbody_cache_reset(rbw);
|
||||
}
|
||||
|
||||
/* Free RigidBody settings and sim instances */
|
||||
void BKE_rigidbody_free_object(Object *ob)
|
||||
{
|
||||
RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (rbo == NULL)
|
||||
return;
|
||||
|
||||
/* free physics references */
|
||||
if (rbo->physics_object) {
|
||||
rbo->physics_object = NULL;
|
||||
}
|
||||
|
||||
if (rbo->physics_shape) {
|
||||
RB_shape_delete(rbo->physics_shape);
|
||||
rbo->physics_shape = NULL;
|
||||
}
|
||||
|
||||
/* free data itself */
|
||||
MEM_freeN(rbo);
|
||||
ob->rigidbody_object = NULL;
|
||||
}
|
||||
|
||||
/* This just copies the data, clearing out references to physics objects.
|
||||
* Anything that uses them MUST verify that the copied object will
|
||||
* be added to relevant groups later...
|
||||
*/
|
||||
RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
|
||||
{
|
||||
RigidBodyOb *rboN = NULL;
|
||||
|
||||
if (ob->rigidbody_object) {
|
||||
/* just duplicate the whole struct first (to catch all the settings) */
|
||||
rboN = MEM_dupallocN(ob->rigidbody_object);
|
||||
|
||||
/* tag object as needing to be verified */
|
||||
rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
|
||||
|
||||
/* clear out all the fields which need to be revalidated later */
|
||||
rboN->physics_object = NULL;
|
||||
rboN->physics_shape = NULL;
|
||||
}
|
||||
|
||||
/* return new copy of settings */
|
||||
return rboN;
|
||||
}
|
||||
|
||||
/* ------------------------ */
|
||||
|
||||
/* Add rigid body constraint to the specified object */
|
||||
RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
|
||||
{
|
||||
RigidBodyCon *rbc;
|
||||
RigidBodyWorld *rbw = scene->rigidbody_world;
|
||||
|
||||
/* sanity checks
|
||||
* - rigidbody world must exist
|
||||
* - object must exist
|
||||
* - cannot add constraint if it already exists
|
||||
*/
|
||||
if (ob == NULL || (ob->rigidbody_constraint != NULL))
|
||||
return NULL;
|
||||
|
||||
/* create new settings data, and link it up */
|
||||
rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon");
|
||||
|
||||
/* set default settings */
|
||||
rbc->type = type;
|
||||
|
||||
rbc->ob1 = NULL;
|
||||
rbc->ob2 = NULL;
|
||||
|
||||
rbc->flag |= RBC_FLAG_ENABLED;
|
||||
rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
|
||||
|
||||
rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
|
||||
rbc->num_solver_iterations = 10; /* 10 is Bullet default */
|
||||
|
||||
rbc->limit_lin_x_lower = -1.0f;
|
||||
rbc->limit_lin_x_upper = 1.0f;
|
||||
rbc->limit_lin_y_lower = -1.0f;
|
||||
rbc->limit_lin_y_upper = 1.0f;
|
||||
rbc->limit_lin_z_lower = -1.0f;
|
||||
rbc->limit_lin_z_upper = 1.0f;
|
||||
rbc->limit_ang_x_lower = -M_PI_4;
|
||||
rbc->limit_ang_x_upper = M_PI_4;
|
||||
rbc->limit_ang_y_lower = -M_PI_4;
|
||||
rbc->limit_ang_y_upper = M_PI_4;
|
||||
rbc->limit_ang_z_lower = -M_PI_4;
|
||||
rbc->limit_ang_z_upper = M_PI_4;
|
||||
|
||||
rbc->spring_damping_x = 0.5f;
|
||||
rbc->spring_damping_y = 0.5f;
|
||||
rbc->spring_damping_z = 0.5f;
|
||||
rbc->spring_stiffness_x = 10.0f;
|
||||
rbc->spring_stiffness_y = 10.0f;
|
||||
rbc->spring_stiffness_z = 10.0f;
|
||||
|
||||
rbc->motor_lin_max_impulse = 1.0f;
|
||||
rbc->motor_lin_target_velocity = 1.0f;
|
||||
rbc->motor_ang_max_impulse = 1.0f;
|
||||
rbc->motor_ang_target_velocity = 1.0f;
|
||||
|
||||
/* flag cache as outdated */
|
||||
BKE_rigidbody_cache_reset(rbw);
|
||||
|
||||
/* return this object */
|
||||
return rbc;
|
||||
}
|
||||
|
||||
void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
|
||||
{
|
||||
RigidBodyWorld *rbw = scene->rigidbody_world;
|
||||
RigidBodyCon *rbc = ob->rigidbody_constraint;
|
||||
|
||||
/* remove from rigidbody world, free object won't do this */
|
||||
if (rbw && rbw->physics_world && rbc->physics_constraint) {
|
||||
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
|
||||
}
|
||||
/* remove object's settings */
|
||||
BKE_rigidbody_free_constraint(ob);
|
||||
|
||||
/* flag cache as outdated */
|
||||
BKE_rigidbody_cache_reset(rbw);
|
||||
}
|
||||
|
||||
/* Free RigidBody constraint and sim instance */
|
||||
void BKE_rigidbody_free_constraint(Object *ob)
|
||||
{
|
||||
RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL;
|
||||
|
||||
/* sanity check */
|
||||
if (rbc == NULL)
|
||||
return;
|
||||
|
||||
/* free physics reference */
|
||||
if (rbc->physics_constraint) {
|
||||
RB_constraint_delete(rbc->physics_constraint);
|
||||
rbc->physics_constraint = NULL;
|
||||
}
|
||||
|
||||
/* free data itself */
|
||||
MEM_freeN(rbc);
|
||||
ob->rigidbody_constraint = NULL;
|
||||
}
|
||||
|
||||
/* This just copies the data, clearing out references to physics objects.
|
||||
* Anything that uses them MUST verify that the copied object will
|
||||
* be added to relevant groups later...
|
||||
*/
|
||||
RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
|
||||
{
|
||||
RigidBodyCon *rbcN = NULL;
|
||||
|
||||
if (ob->rigidbody_constraint) {
|
||||
/* just duplicate the whole struct first (to catch all the settings) */
|
||||
rbcN = MEM_dupallocN(ob->rigidbody_constraint);
|
||||
|
||||
/* tag object as needing to be verified */
|
||||
rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE;
|
||||
|
||||
/* clear out all the fields which need to be revalidated later */
|
||||
rbcN->physics_constraint = NULL;
|
||||
}
|
||||
|
||||
/* return new copy of settings */
|
||||
return rbcN;
|
||||
}
|
||||
|
||||
/* preserve relationships between constraints and rigid bodies after duplication */
|
||||
void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
|
||||
{
|
||||
ID_NEW(rbc->ob1);
|
||||
ID_NEW(rbc->ob2);
|
||||
}
|
||||
|
||||
/* ------------------------ */
|
||||
/* Utilities */
|
||||
|
||||
float BKE_rigidbody_object_mass(RigidBodyOb *rbo)
|
||||
{
|
||||
if (!rbo)
|
||||
return 0.0f;
|
||||
if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED)
|
||||
return 0.0f;
|
||||
return rbo->mass;
|
||||
}
|
||||
|
||||
float BKE_rigidbody_object_margin(RigidBodyOb *rbo)
|
||||
{
|
||||
if (!rbo)
|
||||
return 0.0f;
|
||||
if (rbo->flag & RBO_FLAG_USE_MARGIN || ELEM3(rbo->shape, RB_SHAPE_CONVEXH, RB_SHAPE_TRIMESH, RB_SHAPE_CONE))
|
||||
return rbo->margin;
|
||||
else
|
||||
return 0.04f;
|
||||
}
|
60
source/blender/blenlib/BLI_pagedbuffer.h
Normal file
60
source/blender/blenlib/BLI_pagedbuffer.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef BLI_PAGEDBUFFER_H
|
||||
#define BLI_PAGEDBUFFER_H
|
||||
|
||||
/** \file BLI_pbuffer.h
|
||||
* \ingroup bli
|
||||
* \brief Management and access functions for paged buffers.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
struct bPagedBuffer;
|
||||
|
||||
void BLI_pbuf_init(struct bPagedBuffer *pbuf, size_t page_bytes, size_t elem_bytes);
|
||||
void BLI_pbuf_free(struct bPagedBuffer *pbuf);
|
||||
void BLI_pbuf_copy(struct bPagedBuffer *to, struct bPagedBuffer *from);
|
||||
|
||||
void BLI_pbuf_add_elements(struct bPagedBuffer *pbuf, int num_elem);
|
||||
|
||||
void *BLI_pbuf_get(struct bPagedBuffer *pbuf, int index);
|
||||
|
||||
|
||||
typedef struct bPagedBufferIterator
|
||||
{
|
||||
struct bPagedBufferPage *page;
|
||||
void *data;
|
||||
int index, page_index;
|
||||
} bPagedBufferIterator;
|
||||
|
||||
void BLI_pbuf_iter_init(struct bPagedBuffer *pbuf, struct bPagedBufferIterator *iter);
|
||||
void BLI_pbuf_iter_next(struct bPagedBuffer *pbuf, struct bPagedBufferIterator *iter);
|
||||
bool BLI_pbuf_iter_valid(struct bPagedBuffer *pbuf, struct bPagedBufferIterator *iter);
|
||||
void BLI_pbuf_iter_at(struct bPagedBuffer *pbuf, struct bPagedBufferIterator *iter, int index);
|
||||
|
||||
#endif /* BLI_PAGEDBUFFER_H */
|
@@ -81,6 +81,7 @@ set(SRC
|
||||
intern/math_vector_inline.c
|
||||
intern/md5.c
|
||||
intern/noise.c
|
||||
intern/pagedbuffer.c
|
||||
intern/path_util.c
|
||||
intern/polyfill2d.c
|
||||
intern/quadric.c
|
||||
@@ -154,6 +155,7 @@ set(SRC
|
||||
BLI_memarena.h
|
||||
BLI_mempool.h
|
||||
BLI_noise.h
|
||||
BLI_pagedbuffer.h
|
||||
BLI_path_util.h
|
||||
BLI_polyfill2d.h
|
||||
BLI_quadric.h
|
||||
|
241
source/blender/blenlib/intern/pagedbuffer.c
Normal file
241
source/blender/blenlib/intern/pagedbuffer.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "DNA_pagedbuffer_types.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_pagedbuffer.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
/* XXX how to handle alignment nicely? */
|
||||
/*#define PBUF_ALIGN_STRICT*/
|
||||
|
||||
BLI_INLINE div_t div_ceil(int a, int b)
|
||||
{
|
||||
div_t result = div(a, b);
|
||||
if (result.rem > 0)
|
||||
result.quot += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int pbuf_page_size_from_bytes(size_t page_bytes, size_t elem_bytes)
|
||||
{
|
||||
div_t page_size = div(page_bytes, elem_bytes);
|
||||
#ifdef PBUF_ALIGN_STRICT
|
||||
BLI_assert(page_size.rem == 0);
|
||||
#endif
|
||||
return page_size.quot;
|
||||
}
|
||||
|
||||
static void pbuf_page_alloc(bPagedBuffer *pbuf, int p)
|
||||
{
|
||||
bPagedBufferPage *page = &pbuf->pages[p];
|
||||
if (!page->data) {
|
||||
page->data = MEM_mallocN(pbuf->page_bytes, "paged buffer page");
|
||||
pbuf->totalloc += pbuf->page_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void pbuf_page_free(bPagedBuffer *pbuf, int p)
|
||||
{
|
||||
bPagedBufferPage *page = &pbuf->pages[p];
|
||||
if (page->data) {
|
||||
MEM_freeN(page->data);
|
||||
pbuf->totalloc -= pbuf->page_size;
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PBUF_PAGE_ALLOC_NONE, /* don't allocate any page data */
|
||||
PBUF_PAGE_ALLOC_EXTEND, /* allocate only new page data */
|
||||
PBUF_PAGE_ALLOC_ALL /* allocate all page data */
|
||||
} ePagedBufferPageAlloc;
|
||||
|
||||
static void pbuf_set_totelem(bPagedBuffer *pbuf, int totelem, ePagedBufferPageAlloc alloc_mode)
|
||||
{
|
||||
div_t div_elem = div_ceil(totelem, pbuf->page_size);
|
||||
int totpages = div_elem.quot;
|
||||
// int pagefill = div_elem.rem;
|
||||
if (totpages == 0) {
|
||||
pbuf->pages = NULL;
|
||||
pbuf->totpages = 0;
|
||||
pbuf->totelem = 0;
|
||||
pbuf->totalloc = 0;
|
||||
}
|
||||
else {
|
||||
bPagedBufferPage *pages = MEM_callocN(sizeof(bPagedBufferPage) * totpages, "paged buffer page array");
|
||||
int startp = totelem / pbuf->page_size;
|
||||
int p;
|
||||
|
||||
if (pbuf->pages) {
|
||||
int copyp = min_ii(pbuf->totpages, totpages);
|
||||
memcpy(pages, pbuf->pages, sizeof(bPagedBufferPage) * copyp);
|
||||
MEM_freeN(pbuf->pages);
|
||||
}
|
||||
|
||||
pbuf->pages = pages;
|
||||
pbuf->totpages = totpages;
|
||||
pbuf->totelem = totelem;
|
||||
|
||||
/* init data */
|
||||
switch (alloc_mode) {
|
||||
case PBUF_PAGE_ALLOC_EXTEND:
|
||||
for (p = startp; p < totpages; ++p)
|
||||
pbuf_page_alloc(pbuf, p);
|
||||
break;
|
||||
case PBUF_PAGE_ALLOC_ALL:
|
||||
for (p = 0; p < totpages; ++p)
|
||||
pbuf_page_alloc(pbuf, p);
|
||||
break;
|
||||
case PBUF_PAGE_ALLOC_NONE:
|
||||
/* nothing to do, data pointers are NULL already */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BLI_pbuf_init(bPagedBuffer *pbuf, size_t page_bytes, size_t elem_bytes)
|
||||
{
|
||||
pbuf->page_bytes = page_bytes;
|
||||
pbuf->elem_bytes = elem_bytes;
|
||||
pbuf->page_size = pbuf_page_size_from_bytes(page_bytes, elem_bytes);
|
||||
|
||||
pbuf->pages = NULL;
|
||||
pbuf->totpages = 0;
|
||||
pbuf->totelem = 0;
|
||||
pbuf->totalloc = 0;
|
||||
}
|
||||
|
||||
void BLI_pbuf_free(bPagedBuffer *pbuf)
|
||||
{
|
||||
if (pbuf->pages) {
|
||||
int p;
|
||||
for (p = 0; p < pbuf->totpages; ++p)
|
||||
pbuf_page_free(pbuf, p);
|
||||
MEM_freeN(pbuf->pages);
|
||||
pbuf->pages = NULL;
|
||||
pbuf->totpages = 0;
|
||||
}
|
||||
pbuf->totelem = 0;
|
||||
}
|
||||
|
||||
void BLI_pbuf_copy(bPagedBuffer *to, bPagedBuffer *from)
|
||||
{
|
||||
to->page_bytes = from->page_bytes;
|
||||
to->elem_bytes = from->elem_bytes;
|
||||
to->page_size = from->page_size;
|
||||
|
||||
if (from->pages) {
|
||||
int p;
|
||||
to->pages = MEM_dupallocN(from->pages);
|
||||
for (p = 0; p < from->totpages; ++p)
|
||||
if (from->pages[p].data)
|
||||
to->pages[p].data = MEM_dupallocN(from->pages[p].data);
|
||||
}
|
||||
else {
|
||||
to->pages = NULL;
|
||||
}
|
||||
to->totpages = from->totpages;
|
||||
to->totelem = from->totelem;
|
||||
to->totalloc = from->totalloc;
|
||||
}
|
||||
|
||||
|
||||
void BLI_pbuf_add_elements(bPagedBuffer *pbuf, int num_elem)
|
||||
{
|
||||
int ntotelem = pbuf->totelem + num_elem;
|
||||
pbuf_set_totelem(pbuf, ntotelem, PBUF_PAGE_ALLOC_EXTEND);
|
||||
}
|
||||
|
||||
void *BLI_pbuf_get(bPagedBuffer *pbuf, int index)
|
||||
{
|
||||
if (index < pbuf->totelem) {
|
||||
div_t page_div = div(index, pbuf->page_size);
|
||||
bPagedBufferPage *page = pbuf->pages + page_div.quot;
|
||||
if (page->data)
|
||||
return (char *)page->data + pbuf->elem_bytes * page_div.rem;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void BLI_pbuf_iter_init(bPagedBuffer *pbuf, bPagedBufferIterator *iter)
|
||||
{
|
||||
iter->index = 0;
|
||||
iter->page = pbuf->pages;
|
||||
iter->page_index = 0;
|
||||
if (pbuf->pages) {
|
||||
while (iter->page->data == NULL && iter->index < pbuf->totelem) {
|
||||
iter->index += pbuf->page_size;
|
||||
++iter->page;
|
||||
}
|
||||
iter->data = iter->page->data;
|
||||
}
|
||||
}
|
||||
|
||||
void BLI_pbuf_iter_next(bPagedBuffer *pbuf, bPagedBufferIterator *iter)
|
||||
{
|
||||
++iter->index;
|
||||
++iter->page_index;
|
||||
if (iter->page_index < pbuf->page_size) {
|
||||
iter->data = (char *)iter->data + pbuf->elem_bytes;
|
||||
}
|
||||
else {
|
||||
++iter->page;
|
||||
iter->page_index = 0;
|
||||
while (iter->page->data == NULL && iter->index < pbuf->totelem) {
|
||||
iter->index += pbuf->page_size;
|
||||
++iter->page;
|
||||
}
|
||||
iter->data = iter->page->data;
|
||||
}
|
||||
}
|
||||
|
||||
bool BLI_pbuf_iter_valid(bPagedBuffer *pbuf, bPagedBufferIterator *iter)
|
||||
{
|
||||
return iter->index < pbuf->totelem;
|
||||
}
|
||||
|
||||
void BLI_pbuf_iter_at(bPagedBuffer *pbuf, bPagedBufferIterator *iter, int index)
|
||||
{
|
||||
div_t page_div = div(index, pbuf->page_size);
|
||||
|
||||
iter->index = index;
|
||||
iter->page = pbuf->pages + page_div.quot;
|
||||
iter->page_index = page_div.rem;
|
||||
if (iter->page) {
|
||||
iter->data = (char *)iter->page->data + pbuf->elem_bytes * iter->page_index;
|
||||
}
|
||||
}
|
@@ -79,9 +79,11 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_object_fluidsim.h" // NT
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_pagedbuffer_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_property_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
@@ -134,6 +136,7 @@
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pointcache.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_rigidbody.h"
|
||||
#include "BKE_sca.h" // for init_actuator
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
@@ -4226,6 +4229,47 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
|
||||
}
|
||||
|
||||
|
||||
/* ************ READ PAGED BUFFER ***************** */
|
||||
|
||||
static void direct_link_pagedbuffer(FileData *fd, bPagedBuffer *pbuf)
|
||||
{
|
||||
int p;
|
||||
|
||||
pbuf->pages = newdataadr(fd, pbuf->pages);
|
||||
for (p = 0; p < pbuf->totpages; ++p) {
|
||||
bPagedBufferPage *page = pbuf->pages + p;
|
||||
page->data = newdataadr(fd, page->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ************ READ NPARTICLE BUFFER ***************** */
|
||||
|
||||
static void direct_link_nparticle_display(FileData *fd, NParticleDisplay *display)
|
||||
{
|
||||
link_list(fd, &display->dupli_objects);
|
||||
}
|
||||
|
||||
static void direct_link_nparticle_system(FileData *fd, NParticleSystem *psys)
|
||||
{
|
||||
NParticleAttributeState *attrstate;
|
||||
NParticleDisplay *display;
|
||||
|
||||
link_list(fd, &psys->attributes);
|
||||
|
||||
psys->state = newdataadr(fd, psys->state);
|
||||
if (psys->state) {
|
||||
link_list(fd, &psys->state->attributes);
|
||||
for (attrstate = psys->state->attributes.first; attrstate; attrstate = attrstate->next)
|
||||
direct_link_pagedbuffer(fd, &attrstate->data);
|
||||
}
|
||||
|
||||
link_list(fd, &psys->display);
|
||||
for (display = psys->display.first; display; display = display->next)
|
||||
direct_link_nparticle_display(fd, display);
|
||||
}
|
||||
|
||||
|
||||
/* ************ READ OBJECT ***************** */
|
||||
|
||||
static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
|
||||
@@ -4793,6 +4837,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
|
||||
if (wmd->cmap_curve)
|
||||
direct_link_curvemapping(fd, wmd->cmap_curve);
|
||||
}
|
||||
else if (md->type == eModifierType_NParticleSystem) {
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData *)md;
|
||||
|
||||
pmd->psys = newdataadr(fd, pmd->psys);
|
||||
direct_link_nparticle_system(fd, pmd->psys);
|
||||
}
|
||||
else if (md->type == eModifierType_LaplacianDeform) {
|
||||
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
|
||||
|
||||
@@ -5191,6 +5241,8 @@ static void lib_link_scene(FileData *fd, Main *main)
|
||||
rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints);
|
||||
if (rbw->effector_weights)
|
||||
rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group);
|
||||
/* create empty mempool */
|
||||
BKE_rigidbody_world_init_mempool(rbw);
|
||||
}
|
||||
|
||||
if (sce->nodetree) {
|
||||
|
@@ -116,8 +116,10 @@
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_pagedbuffer_types.h"
|
||||
#include "DNA_packedFile_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_property_types.h"
|
||||
@@ -143,6 +145,7 @@
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_pagedbuffer.h"
|
||||
#include "BLI_mempool.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
@@ -1356,6 +1359,56 @@ static void write_defgroups(WriteData *wd, ListBase *defbase)
|
||||
writestruct(wd, DATA, "bDeformGroup", 1, defgroup);
|
||||
}
|
||||
|
||||
static void write_pagedbuffer(WriteData *wd, bPagedBuffer *pbuf)
|
||||
{
|
||||
int p;
|
||||
|
||||
if (pbuf->pages) {
|
||||
writestruct(wd, DATA, "bPagedBufferPage", pbuf->totpages, pbuf->pages);
|
||||
for (p = 0; p < pbuf->totpages; ++p) {
|
||||
bPagedBufferPage *page = pbuf->pages + p;
|
||||
if (page->data)
|
||||
writedata(wd, DATA, pbuf->page_bytes, page->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write_nparticle_display(WriteData *wd, NParticleDisplay *display)
|
||||
{
|
||||
NParticleDisplayDupliObject *dob;
|
||||
|
||||
writestruct(wd, DATA, "NParticleDisplay", 1, display);
|
||||
|
||||
for (dob = display->dupli_objects.first; dob; dob = dob->next) {
|
||||
writestruct(wd, DATA, "NParticleDisplayDupliObject", 1, dob);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_nparticle_system(WriteData *wd, NParticleSystem *psys)
|
||||
{
|
||||
NParticleAttribute *attr;
|
||||
NParticleDisplay *display;
|
||||
|
||||
writestruct(wd, DATA, "NParticleSystem", 1, psys);
|
||||
for (attr = psys->attributes.first; attr; attr = attr->next) {
|
||||
writestruct(wd, DATA, "NParticleAttribute", 1, attr);
|
||||
}
|
||||
|
||||
if (psys->state) {
|
||||
NParticleAttributeState *attrstate;
|
||||
|
||||
writestruct(wd, DATA, "NParticleState", 1, psys->state);
|
||||
|
||||
for (attrstate = psys->state->attributes.first; attrstate; attrstate = attrstate->next) {
|
||||
writestruct(wd, DATA, "NParticleAttributeState", 1, attrstate);
|
||||
write_pagedbuffer(wd, &attrstate->data);
|
||||
}
|
||||
}
|
||||
|
||||
for (display = psys->display.first; display; display = display->next)
|
||||
write_nparticle_display(wd, display);
|
||||
}
|
||||
|
||||
static void write_modifiers(WriteData *wd, ListBase *modbase)
|
||||
{
|
||||
ModifierData *md;
|
||||
@@ -1473,6 +1526,11 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
|
||||
if (wmd->cmap_curve)
|
||||
write_curvemapping(wd, wmd->cmap_curve);
|
||||
}
|
||||
else if (md->type==eModifierType_NParticleSystem) {
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData *)md;
|
||||
|
||||
write_nparticle_system(wd, pmd->psys);
|
||||
}
|
||||
else if (md->type==eModifierType_LaplacianDeform) {
|
||||
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData*) md;
|
||||
|
||||
@@ -2329,9 +2387,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
|
||||
/* writing RigidBodyWorld data to the blend file */
|
||||
if (sce->rigidbody_world) {
|
||||
writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world);
|
||||
writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights);
|
||||
write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
|
||||
RigidBodyWorld *rbw = sce->rigidbody_world;
|
||||
writestruct(wd, DATA, "RigidBodyWorld", 1, rbw);
|
||||
writestruct(wd, DATA, "EffectorWeights", 1, rbw->effector_weights);
|
||||
write_pointcaches(wd, &rbw->ptcaches);
|
||||
}
|
||||
|
||||
sce= sce->id.next;
|
||||
|
@@ -990,6 +990,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
|
||||
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
|
||||
case eModifierType_LaplacianDeform:
|
||||
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
|
||||
case eModifierType_NParticleSystem:
|
||||
UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
|
||||
/* Default */
|
||||
case eModifierType_None:
|
||||
case eModifierType_ShapeKey:
|
||||
|
@@ -43,6 +43,7 @@ set(SRC
|
||||
drawarmature.c
|
||||
drawmesh.c
|
||||
drawobject.c
|
||||
drawparticles.c
|
||||
drawvolume.c
|
||||
space_view3d.c
|
||||
view3d_buttons.c
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meta_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_smoke_types.h"
|
||||
@@ -7536,6 +7537,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
|
||||
}
|
||||
}
|
||||
|
||||
/* nparticles */
|
||||
if ((md = modifiers_findByType(ob, eModifierType_NParticleSystem))) {
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData *)md;
|
||||
NParticleDisplay *display;
|
||||
|
||||
if (col || (ob->flag & SELECT))
|
||||
cpack(0xFFFFFF);
|
||||
|
||||
glLoadMatrixf(rv3d->viewmat);
|
||||
|
||||
for (display = pmd->psys->display.first; display; display = display->next)
|
||||
draw_nparticles(pmd->psys, display);
|
||||
|
||||
glMultMatrixf(ob->obmat);
|
||||
|
||||
if (col)
|
||||
cpack(col);
|
||||
}
|
||||
|
||||
/* draw code for smoke */
|
||||
if ((md = modifiers_findByType(ob, eModifierType_Smoke))) {
|
||||
SmokeModifierData *smd = (SmokeModifierData *)md;
|
||||
|
72
source/blender/editors/space_view3d/drawparticles.c
Normal file
72
source/blender/editors/space_view3d/drawparticles.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 by the Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/editors/space_view3d/drawparticles.c
|
||||
* \ingroup spview3d
|
||||
*/
|
||||
|
||||
#include "DNA_nparticle_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_nparticle.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
#include "view3d_intern.h"
|
||||
|
||||
static void draw_particles(NParticleSystem *psys, const char *attr_pos)
|
||||
{
|
||||
NParticleIterator it;
|
||||
float pos[3];
|
||||
|
||||
if (!psys->state)
|
||||
return;
|
||||
|
||||
glPointSize(2.0);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
for (BKE_nparticle_iter_init(psys->state, &it); BKE_nparticle_iter_valid(&it); BKE_nparticle_iter_next(&it)) {
|
||||
BKE_nparticle_iter_get_vector(&it, attr_pos, pos);
|
||||
glVertex3fv(pos);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPointSize(1.0);
|
||||
}
|
||||
|
||||
void draw_nparticles(NParticleSystem *psys, NParticleDisplay *display)
|
||||
{
|
||||
switch (display->type) {
|
||||
case PAR_DISPLAY_PARTICLE:
|
||||
draw_particles(psys, display->attribute);
|
||||
break;
|
||||
}
|
||||
}
|
@@ -39,6 +39,8 @@ struct ARegion;
|
||||
struct ARegionType;
|
||||
struct BoundBox;
|
||||
struct DerivedMesh;
|
||||
struct NParticleDisplay;
|
||||
struct NParticleSystem;
|
||||
struct Object;
|
||||
struct SmokeDomainSettings;
|
||||
struct ViewContext;
|
||||
@@ -175,6 +177,9 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, struct DerivedMesh *dm,
|
||||
void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
|
||||
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
|
||||
|
||||
/* drawparticles.c */
|
||||
void draw_nparticles(struct NParticleSystem *psys, struct NParticleDisplay *display);
|
||||
|
||||
/* view3d_draw.c */
|
||||
void view3d_main_area_draw(const struct bContext *C, struct ARegion *ar);
|
||||
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
|
||||
|
@@ -5899,7 +5899,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
||||
if (ob->rigidbody_object && canceled) {
|
||||
float ctime = BKE_scene_frame_get(t->scene);
|
||||
if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime))
|
||||
BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
|
||||
BKE_rigidbody_object_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -82,6 +82,7 @@ typedef enum ModifierType {
|
||||
eModifierType_MeshCache = 46,
|
||||
eModifierType_LaplacianDeform = 47,
|
||||
eModifierType_Wireframe = 48,
|
||||
eModifierType_NParticleSystem = 49,
|
||||
NUM_MODIFIER_TYPES
|
||||
} ModifierType;
|
||||
|
||||
@@ -1362,6 +1363,12 @@ enum {
|
||||
MOD_WIREFRAME_CREASE = (1 << 5),
|
||||
};
|
||||
|
||||
/* nparticle modifier */
|
||||
typedef struct NParticleSystemModifierData {
|
||||
ModifierData modifier;
|
||||
|
||||
struct NParticleSystem *psys;
|
||||
} NParticleSystemModifierData;
|
||||
|
||||
|
||||
#endif /* __DNA_MODIFIER_TYPES_H__ */
|
||||
|
128
source/blender/makesdna/DNA_nparticle_types.h
Normal file
128
source/blender/makesdna/DNA_nparticle_types.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef DNA_NPARTICLE_TYPES_H
|
||||
#define DNA_NPARTICLE_TYPES_H
|
||||
|
||||
/** \file DNA_nparticle_types.h
|
||||
* \ingroup DNA
|
||||
*/
|
||||
|
||||
#include "DNA_pagedbuffer_types.h"
|
||||
|
||||
/* Attribute descriptor */
|
||||
typedef struct NParticleAttributeDescription {
|
||||
char name[64];
|
||||
int datatype;
|
||||
int flag;
|
||||
|
||||
char default_value[64];
|
||||
} NParticleAttributeDescription;
|
||||
|
||||
typedef enum eParticleAttributeFlag {
|
||||
PAR_ATTR_REQUIRED = 1, /* always exists */
|
||||
PAR_ATTR_PROTECTED = 2, /* descriptor is immutable */
|
||||
PAR_ATTR_READONLY = 4, /* attribute data is read-only */
|
||||
PAR_ATTR_TEMPORARY = 8 /* temporary runtime attribute (not stored in cache or blend files) */
|
||||
} eParticleAttributeFlag;
|
||||
|
||||
/* particle attribute types */
|
||||
typedef enum eParticleAttributeDataType {
|
||||
PAR_ATTR_DATATYPE_INTERNAL = 0, /* for static attributes with special types */
|
||||
PAR_ATTR_DATATYPE_FLOAT = 1,
|
||||
PAR_ATTR_DATATYPE_INT = 2,
|
||||
PAR_ATTR_DATATYPE_BOOL = 3,
|
||||
PAR_ATTR_DATATYPE_VECTOR = 4,
|
||||
PAR_ATTR_DATATYPE_POINT = 5,
|
||||
PAR_ATTR_DATATYPE_NORMAL = 6,
|
||||
PAR_ATTR_DATATYPE_QUATERNION = 7,
|
||||
PAR_ATTR_DATATYPE_COLOR = 8,
|
||||
PAR_ATTR_DATATYPE_MATRIX = 9,
|
||||
PAR_ATTR_DATATYPE_POINTER = 10
|
||||
} eParticleAttributeDataType;
|
||||
|
||||
typedef struct NParticleAttributeState {
|
||||
/* XXX next/prev only needed for storing in ListBase,
|
||||
* can be removed when attribute states get stored
|
||||
* in a hash table instead.
|
||||
*/
|
||||
struct NParticleAttributeState *next, *prev;
|
||||
|
||||
int hashkey;
|
||||
int flag;
|
||||
|
||||
NParticleAttributeDescription desc; /* attribute descriptor */
|
||||
bPagedBuffer data;
|
||||
} NParticleAttributeState;
|
||||
|
||||
typedef enum eParticleAttributeStateFlag {
|
||||
PAR_ATTR_STATE_TEST = 1 /* generic temporary test flag */
|
||||
} eParticleAttributeStateFlag;
|
||||
|
||||
typedef struct NParticleState {
|
||||
/* XXX just a list atm, uses linear search for lookup,
|
||||
* could use a GHash instead for O(1) lookup.
|
||||
*/
|
||||
ListBase attributes;
|
||||
|
||||
void *py_handle;
|
||||
} NParticleState;
|
||||
|
||||
typedef struct NParticleAttribute {
|
||||
struct NParticleAttribute *next, *prev;
|
||||
|
||||
NParticleAttributeDescription desc; /* attribute descriptor */
|
||||
} NParticleAttribute;
|
||||
|
||||
typedef struct NParticleSystem {
|
||||
ListBase attributes; /* definition of available attributes */
|
||||
|
||||
struct NParticleState *state; /* current state */
|
||||
|
||||
ListBase display; /* display settings */
|
||||
} NParticleSystem;
|
||||
|
||||
typedef struct NParticleDisplay {
|
||||
struct NParticleDisplay *next, *prev;
|
||||
|
||||
int type;
|
||||
int pad;
|
||||
char attribute[64];
|
||||
|
||||
/* dupli settings */
|
||||
ListBase dupli_objects;
|
||||
} NParticleDisplay;
|
||||
|
||||
typedef struct NParticleDisplayDupliObject {
|
||||
struct NParticleDisplayDupliObject *next, *prev;
|
||||
|
||||
struct Object *object;
|
||||
} NParticleDisplayDupliObject;
|
||||
|
||||
typedef enum eParticleDisplayType {
|
||||
PAR_DISPLAY_PARTICLE = 1,
|
||||
PAR_DISPLAY_DUPLI = 2
|
||||
} eParticleDisplayType;
|
||||
|
||||
#endif /* DNA_NPARTICLE_TYPES_H */
|
@@ -396,7 +396,7 @@ enum {
|
||||
OB_DUPLIVERTS = 1 << 4,
|
||||
OB_DUPLIROT = 1 << 5,
|
||||
OB_DUPLINOSPEED = 1 << 6,
|
||||
/* OB_POWERTRACK = 1 << 7,*/ /*UNUSED*/
|
||||
OB_DUPLI_NPARTICLE = 1 << 7,
|
||||
OB_DUPLIGROUP = 1 << 8,
|
||||
OB_DUPLIFACES = 1 << 9,
|
||||
OB_DUPLIFACES_SCALE = 1 << 10,
|
||||
@@ -405,7 +405,7 @@ enum {
|
||||
OB_NO_CONSTRAINTS = 1 << 13, /* runtime constraints disable */
|
||||
OB_NO_PSYS_UPDATE = 1 << 14, /* hack to work around particle issue */
|
||||
|
||||
OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS,
|
||||
OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS | OB_DUPLI_NPARTICLE,
|
||||
};
|
||||
|
||||
/* (short) ipoflag */
|
||||
|
49
source/blender/makesdna/DNA_pagedbuffer_types.h
Normal file
49
source/blender/makesdna/DNA_pagedbuffer_types.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef DNA_PAGEDBUFFER_H
|
||||
#define DNA_PAGEDBUFFER_H
|
||||
|
||||
/** \file DNA_pagedbuffer.h
|
||||
* \ingroup DNA
|
||||
* \brief bPaged buffers are optimized for dynamic creation and removal of elements.
|
||||
*/
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
typedef struct bPagedBufferPage {
|
||||
void *data; /* layer data */
|
||||
} bPagedBufferPage;
|
||||
|
||||
typedef struct bPagedBuffer {
|
||||
struct bPagedBufferPage *pages; /* page list */
|
||||
int elem_bytes; /* size of a single element in bytes */
|
||||
int page_bytes; /* size of a page in bytes */
|
||||
int page_size; /* elements per page */
|
||||
int totpages; /* number of allocated pages */
|
||||
int totelem; /* number of elements in the buffer */
|
||||
int totalloc; /* actually allocated elements (dead pages not counted) */
|
||||
} bPagedBuffer;
|
||||
|
||||
#endif
|
@@ -55,6 +55,8 @@ typedef struct RigidBodyWorld {
|
||||
|
||||
struct Group *constraints; /* Group containing objects to use for Rigid Body Constraints*/
|
||||
|
||||
struct BLI_mempool *body_pool;
|
||||
|
||||
int pad;
|
||||
float ltime; /* last frame world was evaluated for (internal) */
|
||||
|
||||
|
@@ -135,6 +135,8 @@ static const char *includefiles[] = {
|
||||
"DNA_rigidbody_types.h",
|
||||
"DNA_freestyle_types.h",
|
||||
"DNA_linestyle_types.h",
|
||||
"DNA_pagedbuffer_types.h",
|
||||
"DNA_nparticle_types.h",
|
||||
|
||||
/* empty string to indicate end of includefiles */
|
||||
""
|
||||
@@ -1286,4 +1288,6 @@ int main(int argc, char **argv)
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_freestyle_types.h"
|
||||
#include "DNA_linestyle_types.h"
|
||||
#include "DNA_pagedbuffer_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
/* end of list */
|
||||
|
@@ -66,6 +66,7 @@ set(DEFSRC
|
||||
rna_movieclip.c
|
||||
rna_nla.c
|
||||
rna_nodetree.c
|
||||
rna_nparticle.c
|
||||
rna_object.c
|
||||
rna_object_force.c
|
||||
rna_packedfile.c
|
||||
|
@@ -3262,6 +3262,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_modifier.c", NULL, RNA_def_modifier},
|
||||
{"rna_nla.c", NULL, RNA_def_nla},
|
||||
{"rna_nodetree.c", NULL, RNA_def_nodetree},
|
||||
{"rna_nparticle.c", NULL, RNA_def_nparticle},
|
||||
{"rna_object.c", "rna_object_api.c", RNA_def_object},
|
||||
{"rna_object_force.c", NULL, RNA_def_object_force},
|
||||
{"rna_packedfile.c", NULL, RNA_def_packedfile},
|
||||
|
@@ -161,9 +161,11 @@ void RNA_def_meta(struct BlenderRNA *brna);
|
||||
void RNA_def_modifier(struct BlenderRNA *brna);
|
||||
void RNA_def_nla(struct BlenderRNA *brna);
|
||||
void RNA_def_nodetree(struct BlenderRNA *brna);
|
||||
void RNA_def_nparticle(struct BlenderRNA *brna);
|
||||
void RNA_def_object(struct BlenderRNA *brna);
|
||||
void RNA_def_object_force(struct BlenderRNA *brna);
|
||||
void RNA_def_packedfile(struct BlenderRNA *brna);
|
||||
void RNA_def_pagedbuffer(struct BlenderRNA *brna);
|
||||
void RNA_def_particle(struct BlenderRNA *brna);
|
||||
void RNA_def_pose(struct BlenderRNA *brna);
|
||||
void RNA_def_render(struct BlenderRNA *brna);
|
||||
|
@@ -108,6 +108,7 @@ EnumPropertyItem modifier_type_items[] = {
|
||||
{eModifierType_Smoke, "SMOKE", ICON_MOD_SMOKE, "Smoke", ""},
|
||||
{eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
|
||||
{eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
|
||||
{eModifierType_NParticleSystem, "NPARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particles (new)", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -244,6 +245,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
|
||||
return &RNA_LaplacianDeformModifier;
|
||||
case eModifierType_Wireframe:
|
||||
return &RNA_WireframeModifier;
|
||||
case eModifierType_NParticleSystem:
|
||||
return &RNA_NParticleSystemModifier;
|
||||
/* Default */
|
||||
case eModifierType_None:
|
||||
case eModifierType_ShapeKey:
|
||||
@@ -3652,6 +3655,22 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_nparticlesystem(BlenderRNA *brna)
|
||||
{
|
||||
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleSystemModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna, "NParticle System Modifier", "Particles");
|
||||
RNA_def_struct_sdna(srna, "NParticleSystemModifierData");
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
|
||||
|
||||
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "psys");
|
||||
RNA_def_property_ui_text(prop, "Particle System", "Particle data");
|
||||
}
|
||||
|
||||
void RNA_def_modifier(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -3764,6 +3783,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
||||
rna_def_modifier_meshcache(brna);
|
||||
rna_def_modifier_laplaciandeform(brna);
|
||||
rna_def_modifier_wireframe(brna);
|
||||
rna_def_modifier_nparticlesystem(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
844
source/blender/makesrna/intern/rna_nparticle.c
Normal file
844
source/blender/makesrna/intern/rna_nparticle.c
Normal file
@@ -0,0 +1,844 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/makesrna/intern/rna_nparticle.c
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "DNA_nparticle_types.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
static EnumPropertyItem nparticle_display_type_items[] = {
|
||||
{PAR_DISPLAY_PARTICLE, "PARTICLE", ICON_NONE, "Particles", "Display particle symbols"},
|
||||
{PAR_DISPLAY_DUPLI, "DUPLI", ICON_NONE, "Duplis", "Create object dupli instances from particles"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_pagedbuffer.h"
|
||||
|
||||
#include "BKE_nparticle.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#if 0
|
||||
static StructRNA *rna_NParticleAttributeState_refine(PointerRNA *ptr)
|
||||
{
|
||||
NParticleAttributeState *attrstate = ptr->data;
|
||||
switch (attrstate->desc.datatype) {
|
||||
case PAR_ATTR_DATATYPE_FLOAT:
|
||||
return &RNA_NParticleAttributeStateFloat;
|
||||
case PAR_ATTR_DATATYPE_INT:
|
||||
return &RNA_NParticleAttributeStateInt;
|
||||
case PAR_ATTR_DATATYPE_BOOL:
|
||||
return &RNA_NParticleAttributeStateBool;
|
||||
case PAR_ATTR_DATATYPE_VECTOR:
|
||||
return &RNA_NParticleAttributeStateVector;
|
||||
case PAR_ATTR_DATATYPE_POINT:
|
||||
return &RNA_NParticleAttributeStatePoint;
|
||||
case PAR_ATTR_DATATYPE_NORMAL:
|
||||
return &RNA_NParticleAttributeStateNormal;
|
||||
case PAR_ATTR_DATATYPE_COLOR:
|
||||
return &RNA_NParticleAttributeStateColor;
|
||||
case PAR_ATTR_DATATYPE_MATRIX:
|
||||
return &RNA_NParticleAttributeStateMatrix;
|
||||
|
||||
default:
|
||||
BLI_assert(false); /* unknown data type, should never happen */
|
||||
return &RNA_NParticleAttributeState;
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_NParticleAttributeState_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
NParticleAttributeState *state = ptr->data;
|
||||
bPagedBufferIterator *internal = MEM_callocN(sizeof(bPagedBufferIterator), "particle data iterator");
|
||||
BLI_pbuf_iter_init(&state->data, internal);
|
||||
|
||||
iter->internal = internal;
|
||||
iter->valid = BLI_pbuf_iter_valid(&state->data, internal);
|
||||
}
|
||||
|
||||
static void rna_NParticleAttributeState_data_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
NParticleAttributeState *state = iter->ptr.data;
|
||||
bPagedBufferIterator *internal = iter->internal;
|
||||
BLI_pbuf_iter_next(&state->data, internal);
|
||||
iter->valid = BLI_pbuf_iter_valid(&state->data, internal);
|
||||
}
|
||||
|
||||
static void rna_NParticleAttributeState_data_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
MEM_freeN(iter->internal);
|
||||
iter->internal = NULL;
|
||||
}
|
||||
|
||||
static PointerRNA rna_NParticleAttributeState_data_get(CollectionPropertyIterator *iter, StructRNA *data_srna)
|
||||
{
|
||||
bPagedBufferIterator *internal = iter->internal;
|
||||
PointerRNA ptr;
|
||||
RNA_pointer_create(iter->ptr.id.data, data_srna, internal->data, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int rna_NParticleAttributeState_data_length(PointerRNA *ptr)
|
||||
{
|
||||
NParticleAttributeState *state = ptr->data;
|
||||
return state->data.totelem;
|
||||
}
|
||||
|
||||
int rna_NParticleAttributeState_data_lookup_int(PointerRNA *ptr, int key, PointerRNA *r_ptr, StructRNA *data_srna)
|
||||
{
|
||||
NParticleAttributeState *state = ptr->data;
|
||||
void *data = BLI_pbuf_get(&state->data, key);
|
||||
RNA_pointer_create(ptr->id.data, data_srna, data, r_ptr);
|
||||
return data != NULL;
|
||||
}
|
||||
|
||||
int rna_NParticleAttributeState_data_assign_int(PointerRNA *ptr, int key, const PointerRNA *assign_ptr, StructRNA *UNUSED(data_srna))
|
||||
{
|
||||
NParticleAttributeState *state = ptr->data;
|
||||
void *data = BLI_pbuf_get(&state->data, key);
|
||||
if (data) {
|
||||
memcpy(data, assign_ptr->data, state->data.elem_bytes);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEF_ATTR_TYPE_FUNCS(lcase, ucase) \
|
||||
static PointerRNA rna_NParticleAttributeState_data_get_##lcase (CollectionPropertyIterator *iter) \
|
||||
{ return rna_NParticleAttributeState_data_get(iter, &RNA_NParticleData##ucase); } \
|
||||
static int rna_NParticleAttributeState_data_lookup_int_##lcase (PointerRNA *ptr, int key, PointerRNA *r_ptr) \
|
||||
{ return rna_NParticleAttributeState_data_lookup_int(ptr, key, r_ptr, &RNA_NParticleData##ucase); } \
|
||||
static int rna_NParticleAttributeState_data_assign_int_##lcase (PointerRNA *ptr, int key, const PointerRNA *assign_ptr) \
|
||||
{ return rna_NParticleAttributeState_data_assign_int(ptr, key, assign_ptr, &RNA_NParticleData##ucase); }
|
||||
|
||||
DEF_ATTR_TYPE_FUNCS(float, Float)
|
||||
DEF_ATTR_TYPE_FUNCS(int, Int)
|
||||
DEF_ATTR_TYPE_FUNCS(bool, Bool)
|
||||
DEF_ATTR_TYPE_FUNCS(vector, Vector)
|
||||
DEF_ATTR_TYPE_FUNCS(point, Point)
|
||||
DEF_ATTR_TYPE_FUNCS(normal, Normal)
|
||||
DEF_ATTR_TYPE_FUNCS(color, Color)
|
||||
DEF_ATTR_TYPE_FUNCS(matrix, Matrix)
|
||||
|
||||
#undef DEF_ATTR_TYPE_FUNCS
|
||||
|
||||
static float rna_NParticleDataFloat_get(PointerRNA *ptr)
|
||||
{
|
||||
return *(float *)ptr->data;
|
||||
}
|
||||
|
||||
static void rna_NParticleDataFloat_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
*(float *)ptr->data = value;
|
||||
}
|
||||
|
||||
static int rna_NParticleDataInt_get(PointerRNA *ptr)
|
||||
{
|
||||
return *(int *)ptr->data;
|
||||
}
|
||||
|
||||
static void rna_NParticleDataInt_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
*(int *)ptr->data = value;
|
||||
}
|
||||
|
||||
static int rna_NParticleDataBool_get(PointerRNA *ptr)
|
||||
{
|
||||
return *(bool *)ptr->data;
|
||||
}
|
||||
|
||||
static void rna_NParticleDataBool_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
*(bool *)ptr->data = value;
|
||||
}
|
||||
|
||||
static void rna_NParticleDataVector_get(PointerRNA *ptr, float *result)
|
||||
{
|
||||
copy_v3_v3(result, (float *)ptr->data);
|
||||
}
|
||||
|
||||
static void rna_NParticleDataVector_set(PointerRNA *ptr, const float *value)
|
||||
{
|
||||
copy_v3_v3((float *)ptr->data, value);
|
||||
}
|
||||
|
||||
static void rna_NParticleDataColor_get(PointerRNA *ptr, float *result)
|
||||
{
|
||||
copy_v4_v4(result, (float *)ptr->data);
|
||||
}
|
||||
|
||||
static void rna_NParticleDataColor_set(PointerRNA *ptr, const float *value)
|
||||
{
|
||||
copy_v4_v4((float *)ptr->data, value);
|
||||
}
|
||||
|
||||
static void rna_NParticleDataMatrix_get(PointerRNA *ptr, float *result)
|
||||
{
|
||||
copy_m4_m4((float(*)[4])result, (float(*)[4])ptr->data);
|
||||
}
|
||||
|
||||
static void rna_NParticleDataMatrix_set(PointerRNA *ptr, const float *value)
|
||||
{
|
||||
copy_m4_m4((float(*)[4])ptr->data, (float(*)[4])value);
|
||||
}
|
||||
|
||||
|
||||
static void rna_NParticleState_attributes_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
NParticleState *state = ptr->data;
|
||||
NParticleAttributeState *attrstate = state->attributes.first;
|
||||
|
||||
iter->internal = attrstate;
|
||||
iter->valid = (attrstate != NULL);
|
||||
}
|
||||
|
||||
static void rna_NParticleState_attributes_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
NParticleAttributeState *attrstate = iter->internal;
|
||||
|
||||
attrstate = attrstate->next;
|
||||
|
||||
iter->internal = attrstate;
|
||||
iter->valid = (attrstate != NULL);
|
||||
}
|
||||
|
||||
static void rna_NParticleState_attributes_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
iter->internal = NULL;
|
||||
}
|
||||
|
||||
static PointerRNA rna_NParticleState_attributes_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
NParticleAttributeState *attrstate = iter->internal;
|
||||
PointerRNA ptr;
|
||||
RNA_pointer_create(iter->ptr.id.data, &RNA_NParticleAttributeState, attrstate, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int rna_NParticleState_attributes_length(PointerRNA *ptr)
|
||||
{
|
||||
NParticleState *state = ptr->data;
|
||||
return BLI_countlist(&state->attributes);
|
||||
}
|
||||
|
||||
int rna_NParticleState_attributes_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
|
||||
{
|
||||
NParticleState *state = ptr->data;
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(state, key);
|
||||
RNA_pointer_create(ptr->id.data, &RNA_NParticleAttributeState, attrstate, r_ptr);
|
||||
return attrstate != NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
static void rna_NParticleState_particles_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
NParticleState *state = ptr->data;
|
||||
NParticleIterator *piter = MEM_callocN(sizeof(NParticleIterator), "particle iterator");
|
||||
|
||||
BKE_nparticle_iter_init(state, piter);
|
||||
iter->internal = piter;
|
||||
iter->valid
|
||||
}
|
||||
|
||||
static void rna_NParticleState_particles_next(CollectionPropertyIterator *iter)
|
||||
{
|
||||
NParticleState *state = iter->ptr.data;
|
||||
NParticleIterator *piter = iter->internal;
|
||||
BKE_nparticle_iter_next(piter);
|
||||
iter->valid = BKE_nparticle_iter_valid(piter);
|
||||
}
|
||||
|
||||
static void rna_NParticleState_particles_end(CollectionPropertyIterator *iter)
|
||||
{
|
||||
MEM_freeN(iter->internal);
|
||||
iter->internal = NULL;
|
||||
}
|
||||
|
||||
static PointerRNA rna_NParticleState_particles_get(CollectionPropertyIterator *iter)
|
||||
{
|
||||
NParticleIterator *piter = iter->internal;
|
||||
PointerRNA ptr;
|
||||
RNA_pointer_create(iter->ptr.id.data, &RNA_NParticleIterator, piter, &ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static int rna_NParticleState_particles_length(PointerRNA *ptr)
|
||||
{
|
||||
NParticleState *state = ptr->data;
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(state, "id");
|
||||
if (attrstate)
|
||||
return attrstate->data.totelem;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rna_NParticleState_particles_lookup_int(PointerRNA *ptr, int key, PointerRNA *r_ptr)
|
||||
{
|
||||
/* XXX this is a problem: we cannot return a particle iterator here because
|
||||
* PointerRNA can only reference data that exists permanently in the DNA ...
|
||||
*/
|
||||
NParticleState *state = ptr->data;
|
||||
BKE_nparticle_iter_find_id(state, , NParticleID id)
|
||||
BKE_nparticle_
|
||||
void *data = BLI_pbuf_get(&state->data, key);
|
||||
RNA_pointer_create(ptr->id.data, data_srna, data, r_ptr);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rna_NParticleState_find_particle(NParticleState *state, int id)
|
||||
{
|
||||
return BKE_nparticle_find_index(state, (NParticleID)id);
|
||||
}
|
||||
|
||||
static int rna_NParticleState_add_particle(NParticleState *state, int id)
|
||||
{
|
||||
return BKE_nparticle_add(state, (NParticleID)id);
|
||||
}
|
||||
|
||||
static void rna_NParticleState_remove_particle(NParticleState *state, int id)
|
||||
{
|
||||
BKE_nparticle_remove(state, (NParticleID)id);
|
||||
}
|
||||
|
||||
|
||||
static void rna_NParticleAttribute_update(Main *main, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
/* XXX TODO */
|
||||
}
|
||||
|
||||
static int rna_NParticleAttribute_editable(PointerRNA *ptr)
|
||||
{
|
||||
NParticleAttribute *attr = ptr->data;
|
||||
return !(attr->desc.flag & (PAR_ATTR_PROTECTED | PAR_ATTR_REQUIRED));
|
||||
}
|
||||
|
||||
static NParticleAttribute *rna_NParticleSystem_attributes_new(NParticleSystem *psys, ReportList *reports, const char *name, int datatype)
|
||||
{
|
||||
if (BKE_nparticle_attribute_find(psys, name)) {
|
||||
BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Particle attribute with name %s already exists", name);
|
||||
return NULL;
|
||||
}
|
||||
return BKE_nparticle_attribute_new(psys, name, datatype, 0);
|
||||
}
|
||||
|
||||
static void rna_NParticleSystem_attributes_remove(NParticleSystem *psys, NParticleAttribute *attr)
|
||||
{
|
||||
BKE_nparticle_attribute_remove(psys, attr);
|
||||
}
|
||||
|
||||
static void rna_NParticleSystem_attributes_clear(NParticleSystem *psys)
|
||||
{
|
||||
BKE_nparticle_attribute_remove_all(psys);
|
||||
}
|
||||
|
||||
static void rna_NParticleSystem_attributes_move(NParticleSystem *psys, int from_index, int to_index)
|
||||
{
|
||||
BKE_nparticle_attribute_move(psys, from_index, to_index);
|
||||
}
|
||||
|
||||
static StructRNA *rna_NParticleDisplay_refine(PointerRNA *ptr)
|
||||
{
|
||||
NParticleDisplay *display = ptr->data;
|
||||
|
||||
switch (display->type) {
|
||||
case PAR_DISPLAY_PARTICLE: return &RNA_NParticleDisplayParticle;
|
||||
case PAR_DISPLAY_DUPLI: return &RNA_NParticleDisplayDupli;
|
||||
default: return &RNA_NParticleDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
static NParticleDisplayDupliObject *rna_NParticleDisplayDupli_dupli_objects_new(NParticleDisplay *display)
|
||||
{
|
||||
return BKE_nparticle_display_dupli_object_add(display);
|
||||
}
|
||||
|
||||
static void rna_NParticleDisplayDupli_dupli_objects_remove(NParticleDisplay *display, NParticleDisplayDupliObject *dupli_object)
|
||||
{
|
||||
BKE_nparticle_display_dupli_object_remove(display, dupli_object);
|
||||
}
|
||||
|
||||
static void rna_NParticleDisplayDupli_dupli_objects_clear(NParticleDisplay *display)
|
||||
{
|
||||
BKE_nparticle_display_dupli_object_remove_all(display);
|
||||
}
|
||||
|
||||
static void rna_NParticleDisplayDupli_dupli_objects_move(NParticleDisplay *display, int from_index, int to_index)
|
||||
{
|
||||
BKE_nparticle_display_dupli_object_move(display, from_index, to_index);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
EnumPropertyItem nparticle_attribute_datatype_all[] = {
|
||||
{PAR_ATTR_DATATYPE_INTERNAL, "INTERNAL", 0, "Internal" ""},
|
||||
{PAR_ATTR_DATATYPE_FLOAT, "FLOAT", 0, "Float" ""},
|
||||
{PAR_ATTR_DATATYPE_INT, "INT", 0, "Int" ""},
|
||||
{PAR_ATTR_DATATYPE_BOOL, "BOOL", 0, "Bool" ""},
|
||||
{PAR_ATTR_DATATYPE_VECTOR, "VECTOR", 0, "Vector" ""},
|
||||
{PAR_ATTR_DATATYPE_POINT, "POINT", 0, "Point" ""},
|
||||
{PAR_ATTR_DATATYPE_NORMAL, "NORMAL", 0, "Normal" ""},
|
||||
{PAR_ATTR_DATATYPE_COLOR, "COLOR", 0, "Color" ""},
|
||||
{PAR_ATTR_DATATYPE_MATRIX, "MATRIX", 0, "Matrix" ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem nparticle_attribute_datatype_user[] = {
|
||||
{PAR_ATTR_DATATYPE_FLOAT, "FLOAT", 0, "Float" ""},
|
||||
{PAR_ATTR_DATATYPE_INT, "INT", 0, "Int" ""},
|
||||
{PAR_ATTR_DATATYPE_BOOL, "BOOL", 0, "Bool" ""},
|
||||
{PAR_ATTR_DATATYPE_VECTOR, "VECTOR", 0, "Vector" ""},
|
||||
{PAR_ATTR_DATATYPE_POINT, "POINT", 0, "Point" ""},
|
||||
{PAR_ATTR_DATATYPE_NORMAL, "NORMAL", 0, "Normal" ""},
|
||||
{PAR_ATTR_DATATYPE_COLOR, "COLOR", 0, "Color" ""},
|
||||
{PAR_ATTR_DATATYPE_MATRIX, "MATRIX", 0, "Matrix" ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static void def_nparticle_attribute_description(StructRNA *srna, int update_flag, const char *update_cb, const char *editable_cb)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "desc.name");
|
||||
RNA_def_property_ui_text(prop, "Name", "Unique name");
|
||||
if (update_cb) {
|
||||
if (editable_cb)
|
||||
RNA_def_property_editable_func(prop, editable_cb);
|
||||
RNA_def_property_update(prop, update_flag, update_cb);
|
||||
}
|
||||
else
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "datatype", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "desc.datatype");
|
||||
RNA_def_property_enum_items(prop, nparticle_attribute_datatype_all);
|
||||
RNA_def_property_ui_text(prop, "Data Type", "Basic data type");
|
||||
if (update_cb) {
|
||||
if (editable_cb)
|
||||
RNA_def_property_editable_func(prop, editable_cb);
|
||||
RNA_def_property_update(prop, update_flag, update_cb);
|
||||
}
|
||||
else
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* defines a subtype of NParticleAttribute with a specific collection property for actual data */
|
||||
static void def_nparticle_attribute_state_type(BlenderRNA *brna,
|
||||
const char *state_structname, const char *data_structname,
|
||||
const char *get_func, const char *lookup_int_func, const char *assign_int_func)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, state_structname, "NParticleAttributeState");
|
||||
RNA_def_struct_sdna(srna, "NParticleAttributeState");
|
||||
|
||||
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, data_structname);
|
||||
RNA_def_property_ui_text(prop, "Data", "");
|
||||
RNA_def_property_collection_funcs(prop, "rna_NParticleAttributeState_data_begin", "rna_NParticleAttributeState_data_next",
|
||||
"rna_NParticleAttributeState_data_end", get_func,
|
||||
"rna_NParticleAttributeState_data_length", lookup_int_func,
|
||||
NULL, assign_int_func);
|
||||
}
|
||||
|
||||
/* Subtypes for data access */
|
||||
static void rna_def_nparticle_attribute_data_types(BlenderRNA *brna, bool readonly)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* VOID */
|
||||
if (readonly) {
|
||||
srna = RNA_def_struct(brna, "NParticleDataVoid", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Data", "Unknown particle data type");
|
||||
}
|
||||
|
||||
/* FLOAT */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataFloatReadonly" : "NParticleDataFloat", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Float Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataFloat_get", readonly ? NULL : "rna_NParticleDataFloat_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* INT */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataIntReadonly" : "NParticleDataInt", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Int Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_funcs(prop, "rna_NParticleDataInt_get", readonly ? NULL : "rna_NParticleDataInt_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* BOOL */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataBoolReadonly" : "NParticleDataBool", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Bool Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_NParticleDataBool_get", readonly ? NULL : "rna_NParticleDataBool_set");
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* VECTOR */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataVectorReadonly" : "NParticleDataVector", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Vector Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_XYZ);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataVector_get", readonly ? NULL : "rna_NParticleDataVector_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* POINT */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataPointReadonly" : "NParticleDataPoint", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Point Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataVector_get", readonly ? NULL : "rna_NParticleDataVector_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* NORMAL */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataNormalReadonly" : "NParticleDataNormal", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Normal Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_DIRECTION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataVector_get", readonly ? NULL : "rna_NParticleDataVector_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* COLOR */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataColorReadonly" : "NParticleDataColor", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Color Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataColor_get", readonly ? NULL : "rna_NParticleDataColor_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
/* MATRIX */
|
||||
srna = RNA_def_struct(brna, readonly ? "NParticleDataMatrixReadonly" : "NParticleDataMatrix", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Matrix Data", "");
|
||||
|
||||
prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_MATRIX);
|
||||
RNA_def_property_array(prop, 16);
|
||||
RNA_def_property_float_funcs(prop, "rna_NParticleDataMatrix_get", readonly ? NULL : "rna_NParticleDataMatrix_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Value", "");
|
||||
if (readonly)
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_attribute_state(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleAttributeState", NULL);
|
||||
RNA_def_struct_sdna(srna, "NParticleAttributeState");
|
||||
RNA_def_struct_ui_text(srna, "Particle Attribute State", "Data for a particle attribute");
|
||||
RNA_def_struct_refine_func(srna, "rna_NParticleAttributeState_refine");
|
||||
|
||||
def_nparticle_attribute_description(srna, 0, NULL, NULL);
|
||||
|
||||
rna_def_nparticle_attribute_data_types(brna, false);
|
||||
rna_def_nparticle_attribute_data_types(brna, true);
|
||||
|
||||
#define DEF_ATTR_TYPE_RNA(lcase, ucase) \
|
||||
def_nparticle_attribute_state_type(brna, "NParticleAttributeState"#ucase, "NParticleData"#ucase, \
|
||||
"rna_NParticleAttributeState_data_get_"#lcase, \
|
||||
"rna_NParticleAttributeState_data_lookup_int_"#lcase, \
|
||||
"rna_NParticleAttributeState_data_assign_int_"#lcase);
|
||||
|
||||
DEF_ATTR_TYPE_RNA(float, Float)
|
||||
DEF_ATTR_TYPE_RNA(int, Int)
|
||||
DEF_ATTR_TYPE_RNA(bool, Bool)
|
||||
DEF_ATTR_TYPE_RNA(vector, Vector)
|
||||
DEF_ATTR_TYPE_RNA(point, Point)
|
||||
DEF_ATTR_TYPE_RNA(normal, Normal)
|
||||
DEF_ATTR_TYPE_RNA(color, Color)
|
||||
DEF_ATTR_TYPE_RNA(matrix, Matrix)
|
||||
|
||||
#undef DEF_ATTR_TYPE_RNA
|
||||
}
|
||||
#endif
|
||||
|
||||
static void rna_def_nparticle_iterator(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleIterator", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Iterator", "Access iterator for individual particles");
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_state(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop, *parm;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleState", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle State", "Data in a particle system for a specific frame");
|
||||
|
||||
#if 0
|
||||
prop = RNA_def_property(srna, "attributes", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_funcs(prop, "rna_NParticleState_attributes_begin", "rna_NParticleState_attributes_next",
|
||||
"rna_NParticleState_attributes_end", "rna_NParticleState_attributes_get",
|
||||
"rna_NParticleState_attributes_length", NULL,
|
||||
"rna_NParticleState_attributes_lookup_string", NULL);
|
||||
RNA_def_property_ui_text(prop, "Attributes", "Data layers associated to particles");
|
||||
RNA_def_property_struct_type(prop, "NParticleAttributeState");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
prop = RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "NParticleIterator");
|
||||
RNA_def_property_ui_text(prop, "Particles", "");
|
||||
RNA_def_property_collection_funcs(prop, "rna_NParticleState_particles_begin", "rna_NParticleState_particles_next",
|
||||
"rna_NParticleState_particles_end", "rna_NParticleState_particles_get",
|
||||
"rna_NParticleState_particles_length", "rna_NParticleState_particles_lookup_int",
|
||||
NULL, NULL);
|
||||
#endif
|
||||
|
||||
func = RNA_def_function(srna, "find_particle", "rna_NParticleState_find_particle");
|
||||
RNA_def_function_ui_description(func, "Get a particle's index");
|
||||
parm = RNA_def_int(func, "id", 0, INT_MIN, INT_MAX, "Identifier", "Unique identifier of the particle", INT_MIN, INT_MAX);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
/* return value */
|
||||
parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Index of the particle in attribute states", 0, INT_MAX);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "add_particle", "rna_NParticleState_add_particle");
|
||||
RNA_def_function_ui_description(func, "Add a particle");
|
||||
parm = RNA_def_int(func, "id", 0, INT_MIN, INT_MAX, "Identifier", "Unique identifier of the particle", INT_MIN, INT_MAX);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
/* return value */
|
||||
parm = RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Index of the particle in attribute states", 0, INT_MAX);
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove_particle", "rna_NParticleState_remove_particle");
|
||||
RNA_def_function_ui_description(func, "Remove a particle");
|
||||
parm = RNA_def_int(func, "id", 0, INT_MIN, INT_MAX, "Identifier", "Unique identifier of the particle", INT_MIN, INT_MAX);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
}
|
||||
|
||||
|
||||
static void rna_def_nparticle_attribute(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleAttribute", NULL);
|
||||
RNA_def_struct_sdna(srna, "NParticleAttribute");
|
||||
RNA_def_struct_ui_text(srna, "Particle Attribute", "Attribute in a particle system");
|
||||
|
||||
def_nparticle_attribute_description(srna, 0, "rna_NParticleAttribute_update", "rna_NParticleAttribute_editable");
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_system_attributes_api(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_def_property_srna(cprop, "NParticleAttributes");
|
||||
srna = RNA_def_struct(brna, "NParticleAttributes", NULL);
|
||||
RNA_def_struct_sdna(srna, "NParticleSystem");
|
||||
RNA_def_struct_ui_text(srna, "Attributes", "Collection of particle attributes");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_NParticleSystem_attributes_new");
|
||||
RNA_def_function_ui_description(func, "Add a particle attribute");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm = RNA_def_string(func, "name", NULL, 64, "Name", "");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm = RNA_def_enum(func, "datatype", nparticle_attribute_datatype_user, PAR_ATTR_DATATYPE_FLOAT, "Data Type", "Base data type");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
/* return value */
|
||||
parm = RNA_def_pointer(func, "attr", "NParticleAttribute", "", "Attribute");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_NParticleSystem_attributes_remove");
|
||||
RNA_def_function_ui_description(func, "Remove an attribute from the buffer");
|
||||
parm = RNA_def_pointer(func, "attr", "NParticleAttribute", "", "The attribute to remove");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "clear", "rna_NParticleSystem_attributes_clear");
|
||||
RNA_def_function_ui_description(func, "Remove all attributes from the buffer");
|
||||
|
||||
func = RNA_def_function(srna, "move", "rna_NParticleSystem_attributes_move");
|
||||
RNA_def_function_ui_description(func, "Move an attribute to another position");
|
||||
parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the attribute to move", 0, 10000);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the attribute", 0, 10000);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_display_dupli_object(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleDisplayDupliObject", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Display Dupli Object", "Object dupli settings");
|
||||
|
||||
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "object");
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Object", "Object to use for dupli instances");
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_display_dupli_objects_api(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *parm;
|
||||
FunctionRNA *func;
|
||||
|
||||
RNA_def_property_srna(cprop, "NParticleDisplayDupliObjects");
|
||||
srna = RNA_def_struct(brna, "NParticleDisplayDupliObjects", NULL);
|
||||
RNA_def_struct_sdna(srna, "NParticleDisplay");
|
||||
RNA_def_struct_ui_text(srna, "Dupli Objects", "Collection of dupli objects in a particle system");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_NParticleDisplayDupli_dupli_objects_new");
|
||||
RNA_def_function_ui_description(func, "Add a particle dupli object");
|
||||
/* return value */
|
||||
parm = RNA_def_pointer(func, "dupli_object", "NParticleDisplayDupliObject", "Dupli Object", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_NParticleDisplayDupli_dupli_objects_remove");
|
||||
RNA_def_function_ui_description(func, "Remove an particle dupli object");
|
||||
parm = RNA_def_pointer(func, "dupli_object", "NParticleDisplayDupliObject", "", "The dupli object to remove");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "clear", "rna_NParticleDisplayDupli_dupli_objects_clear");
|
||||
RNA_def_function_ui_description(func, "Remove all particle dupli objects");
|
||||
|
||||
func = RNA_def_function(srna, "move", "rna_NParticleDisplayDupli_dupli_objects_move");
|
||||
RNA_def_function_ui_description(func, "Move a particle dupli object to another index");
|
||||
parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the attribute to move", 0, 10000);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the attribute", 0, 10000);
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED);
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_display(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleDisplay", NULL);
|
||||
RNA_def_struct_sdna(srna, "NParticleDisplay");
|
||||
RNA_def_struct_ui_text(srna, "Particle Display", "Display mode for particles");
|
||||
RNA_def_struct_refine_func(srna, "rna_NParticleDisplay_refine");
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, nparticle_display_type_items);
|
||||
RNA_def_property_ui_text(prop, "Type", "");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleDisplayParticle", "NParticleDisplay");
|
||||
RNA_def_struct_sdna(srna, "NParticleDisplay");
|
||||
RNA_def_struct_ui_text(srna, "Particle Symbol Display", "Displays particle symbols");
|
||||
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleDisplayDupli", "NParticleDisplay");
|
||||
RNA_def_struct_sdna(srna, "NParticleDisplay");
|
||||
RNA_def_struct_ui_text(srna, "Particle Dupli Display", "Create object dupli instances");
|
||||
|
||||
prop = RNA_def_property(srna, "dupli_objects", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "dupli_objects", NULL);
|
||||
RNA_def_property_ui_text(prop, "Dupli Objects", "Usable objects for dupli instances");
|
||||
RNA_def_property_struct_type(prop, "NParticleDisplayDupliObject");
|
||||
rna_def_nparticle_display_dupli_objects_api(brna, prop);
|
||||
}
|
||||
|
||||
static void rna_def_nparticle_system(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "NParticleSystem", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle System", "Container for particles");
|
||||
|
||||
prop = RNA_def_property(srna, "attributes", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "attributes", NULL);
|
||||
RNA_def_property_ui_text(prop, "Attributes", "Data layers associated to particles");
|
||||
RNA_def_property_struct_type(prop, "NParticleAttribute");
|
||||
rna_def_nparticle_system_attributes_api(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "state", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "state");
|
||||
RNA_def_property_struct_type(prop, "NParticleState");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "State", "");
|
||||
|
||||
prop = RNA_def_property(srna, "display", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_collection_sdna(prop, NULL, "display", NULL);
|
||||
RNA_def_property_ui_text(prop, "Display", "Display modes");
|
||||
RNA_def_property_struct_type(prop, "NParticleDisplay");
|
||||
}
|
||||
|
||||
void RNA_def_nparticle(BlenderRNA *brna)
|
||||
{
|
||||
#if 0
|
||||
rna_def_nparticle_attribute_state(brna);
|
||||
#endif
|
||||
rna_def_nparticle_iterator(brna);
|
||||
rna_def_nparticle_state(brna);
|
||||
rna_def_nparticle_attribute(brna);
|
||||
rna_def_nparticle_display_dupli_object(brna);
|
||||
rna_def_nparticle_display(brna);
|
||||
rna_def_nparticle_system(brna);
|
||||
}
|
||||
|
||||
#endif
|
@@ -192,7 +192,7 @@ static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value)
|
||||
#ifdef WITH_BULLET
|
||||
/* update kinematic state if necessary - only needed for active bodies */
|
||||
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
|
||||
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
|
||||
RB_body_set_mass(rbo->physics_object, BKE_rigidbody_object_mass(rbo));
|
||||
RB_body_set_kinematic_state(rbo->physics_object, !value);
|
||||
rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
|
||||
}
|
||||
@@ -208,7 +208,7 @@ static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value)
|
||||
#ifdef WITH_BULLET
|
||||
/* only active bodies need mass update */
|
||||
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
|
||||
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
|
||||
RB_body_set_mass(rbo->physics_object, BKE_rigidbody_object_mass(rbo));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -246,7 +246,7 @@ static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value)
|
||||
|
||||
#ifdef WITH_BULLET
|
||||
if (rbo->physics_shape) {
|
||||
RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
|
||||
RB_shape_set_margin(rbo->physics_shape, BKE_rigidbody_object_margin(rbo));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -274,7 +274,7 @@ static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value)
|
||||
#ifdef WITH_BULLET
|
||||
/* update kinematic state if necessary */
|
||||
if (rbo->physics_object) {
|
||||
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
|
||||
RB_body_set_mass(rbo->physics_object, BKE_rigidbody_object_mass(rbo));
|
||||
RB_body_set_kinematic_state(rbo->physics_object, value);
|
||||
rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
|
||||
}
|
||||
|
@@ -73,6 +73,7 @@ set(SRC
|
||||
intern/MOD_mirror.c
|
||||
intern/MOD_multires.c
|
||||
intern/MOD_none.c
|
||||
intern/MOD_nparticle.c
|
||||
intern/MOD_ocean.c
|
||||
intern/MOD_particleinstance.c
|
||||
intern/MOD_particlesystem.c
|
||||
|
@@ -81,6 +81,7 @@ extern ModifierTypeInfo modifierType_UVWarp;
|
||||
extern ModifierTypeInfo modifierType_MeshCache;
|
||||
extern ModifierTypeInfo modifierType_LaplacianDeform;
|
||||
extern ModifierTypeInfo modifierType_Wireframe;
|
||||
extern ModifierTypeInfo modifierType_NParticleSystem;
|
||||
|
||||
/* MOD_util.c */
|
||||
void modifier_type_init(ModifierTypeInfo *types[]);
|
||||
|
126
source/blender/modifiers/intern/MOD_nparticle.c
Normal file
126
source/blender/modifiers/intern/MOD_nparticle.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file blender/modifiers/intern/MOD_nparticles.c
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_nparticle_types.h"
|
||||
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_nparticle.h"
|
||||
|
||||
struct DerivedMesh;
|
||||
struct Object;
|
||||
|
||||
static void nparticle_system_initData(ModifierData *md)
|
||||
{
|
||||
NParticleSystemModifierData *pmd= (NParticleSystemModifierData *)md;
|
||||
|
||||
pmd->psys = BKE_nparticle_system_new();
|
||||
|
||||
/* add default particle display */
|
||||
BKE_nparticle_display_add(pmd->psys, PAR_DISPLAY_PARTICLE);
|
||||
BKE_nparticle_display_add(pmd->psys, PAR_DISPLAY_DUPLI);
|
||||
}
|
||||
|
||||
static void nparticle_system_freeData(ModifierData *md)
|
||||
{
|
||||
NParticleSystemModifierData *pmd= (NParticleSystemModifierData *)md;
|
||||
|
||||
BKE_nparticle_system_free(pmd->psys);
|
||||
pmd->psys = NULL;
|
||||
}
|
||||
|
||||
static void nparticle_system_copyData(ModifierData *md, ModifierData *target)
|
||||
{
|
||||
NParticleSystemModifierData *pmd= (NParticleSystemModifierData *)md;
|
||||
NParticleSystemModifierData *tpmd= (NParticleSystemModifierData *)target;
|
||||
|
||||
tpmd->psys = BKE_nparticle_system_copy(pmd->psys);
|
||||
}
|
||||
|
||||
static struct DerivedMesh *nparticle_system_applyModifier(ModifierData *UNUSED(md), struct Object *UNUSED(ob),
|
||||
struct DerivedMesh *derivedData,
|
||||
ModifierApplyFlag UNUSED(flag))
|
||||
{
|
||||
/*NParticleSystemModifierData *pmd= (NParticleSystemModifierData *)md;*/
|
||||
return derivedData;
|
||||
}
|
||||
|
||||
static void nparticle_system_foreachObjectLink(ModifierData *md, struct Object *ob,
|
||||
void (*walk)(void *userData, struct Object *ob, struct Object **obpoin),
|
||||
void *userData)
|
||||
{
|
||||
NParticleSystemModifierData *pmd = (NParticleSystemModifierData *)md;
|
||||
NParticleDisplay *display;
|
||||
|
||||
for (display = pmd->psys->display.first; display; display = display->next) {
|
||||
switch (display->type) {
|
||||
case PAR_DISPLAY_DUPLI: {
|
||||
NParticleDisplayDupliObject *dob;
|
||||
for (dob = display->dupli_objects.first; dob; dob = dob->next) {
|
||||
walk(userData, ob, &dob->object);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModifierTypeInfo modifierType_NParticleSystem = {
|
||||
/* name */ "Particles",
|
||||
/* structName */ "NParticleSystemModifierData",
|
||||
/* structSize */ sizeof(NParticleSystemModifierData),
|
||||
/* type */ eModifierTypeType_NonGeometrical,
|
||||
/* flags */ eModifierTypeFlag_AcceptsMesh /* for now only allow single particle buffer for unambiguous access */
|
||||
| eModifierTypeFlag_Single
|
||||
| eModifierTypeFlag_UsesPointCache,
|
||||
|
||||
/* copyData */ nparticle_system_copyData,
|
||||
/* deformVerts */ NULL,
|
||||
/* deformVertsEM */ NULL,
|
||||
/* deformMatrices */ NULL,
|
||||
/* deformMatricesEM */ NULL,
|
||||
/* applyModifier */ nparticle_system_applyModifier,
|
||||
/* applyModifierEM */ NULL,
|
||||
/* initData */ nparticle_system_initData,
|
||||
/* requiredDataMask */ NULL,
|
||||
/* freeData */ nparticle_system_freeData,
|
||||
/* isDisabled */ NULL,
|
||||
/* updateDepgraph */ NULL,
|
||||
/* dependsOnTime */ NULL,
|
||||
/* dependsOnNormals */ NULL,
|
||||
/* foreachObjectLink */ nparticle_system_foreachObjectLink,
|
||||
/* foreachIDLink */ NULL,
|
||||
};
|
@@ -309,5 +309,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
||||
INIT_TYPE(MeshCache);
|
||||
INIT_TYPE(LaplacianDeform);
|
||||
INIT_TYPE(Wireframe);
|
||||
INIT_TYPE(NParticleSystem);
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
@@ -20,3 +20,4 @@ add_subdirectory(intern)
|
||||
add_subdirectory(generic)
|
||||
add_subdirectory(mathutils)
|
||||
add_subdirectory(bmesh)
|
||||
add_subdirectory(bparticles)
|
||||
|
41
source/blender/python/bparticles/CMakeLists.txt
Normal file
41
source/blender/python/bparticles/CMakeLists.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# Contributor(s): Campbell Barton
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../makesdna
|
||||
../../../../intern/guardedalloc
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(SRC
|
||||
bparticles_py_api.c
|
||||
bparticles_py_types.c
|
||||
|
||||
bparticles_py_api.h
|
||||
bparticles_py_types.h
|
||||
)
|
||||
|
||||
blender_add_lib(bf_python_bparticles "${SRC}" "${INC}" "${INC_SYS}")
|
167
source/blender/python/bparticles/bparticles_py_api.c
Normal file
167
source/blender/python/bparticles/bparticles_py_api.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/bparticles/bparticles_py_api.c
|
||||
* \ingroup pybparticles
|
||||
*
|
||||
* This file defines the 'bparticles' module.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_nparticle_types.h"
|
||||
|
||||
#include "BKE_nparticle.h"
|
||||
|
||||
#include "bparticles_py_types.h"
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include "bparticles_py_api.h" /* own include */
|
||||
#include "bparticles_py_types.h"
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_new_doc,
|
||||
".. method:: new()\n"
|
||||
"\n"
|
||||
" :arg psys: The particle system.\n"
|
||||
" :type psys: :class:`bpy.types.NParticleSystem`\n"
|
||||
" :return: Return a new, empty NParticleState.\n"
|
||||
" :rtype: :class:`bparticles.types.NParticleState`\n"
|
||||
);
|
||||
static PyObject *bpy_bpar_new(PyObject *UNUSED(self), PyObject *value)
|
||||
{
|
||||
NParticleSystem *psys = PyC_RNA_AsPointer(value, "NParticleSystem");
|
||||
NParticleState *state;
|
||||
|
||||
if (!psys)
|
||||
return NULL;
|
||||
|
||||
state = BKE_nparticle_state_new(psys);
|
||||
|
||||
return BPy_NParticleState_CreatePyObject(state);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_copy_doc,
|
||||
".. method:: copy()\n"
|
||||
"\n"
|
||||
" :arg psys: The particle system.\n"
|
||||
" :type psys: :class:`bpy.types.NParticleSystem`\n"
|
||||
" :return: Return a copy of the current NParticleState.\n"
|
||||
" :rtype: :class:`bparticles.types.NParticleState`\n"
|
||||
);
|
||||
static PyObject *bpy_bpar_copy(PyObject *UNUSED(self), PyObject *value)
|
||||
{
|
||||
NParticleSystem *psys = PyC_RNA_AsPointer(value, "NParticleSystem");
|
||||
NParticleState *state;
|
||||
|
||||
if (!psys)
|
||||
return NULL;
|
||||
|
||||
if (psys->state)
|
||||
state = BKE_nparticle_state_copy(psys->state);
|
||||
else
|
||||
state = BKE_nparticle_state_new(psys);
|
||||
|
||||
return BPy_NParticleState_CreatePyObject(state);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_set_current_state_doc,
|
||||
".. method:: set_current_state()\n"
|
||||
"\n"
|
||||
" :arg psys: The particle system.\n"
|
||||
" :type psys: :class:`bpy.types.NParticleSystem`\n"
|
||||
" :arg state: The particle state.\n"
|
||||
" :type state: :class:`bparticles.types.NParticleState`\n"
|
||||
);
|
||||
static PyObject *bpy_bpar_set_current_state(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
|
||||
{
|
||||
static const char *kwlist[] = {"psys", "state", NULL};
|
||||
PyObject *py_psys;
|
||||
BPy_NParticleState *py_state;
|
||||
NParticleSystem *psys;
|
||||
NParticleState *state;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO:set_current_state", (char **)kwlist,
|
||||
&py_psys, &py_state))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
psys = PyC_RNA_AsPointer(py_psys, "NParticleSystem");
|
||||
state = BPy_NParticleState_Check(py_state) ? py_state->state : NULL;
|
||||
|
||||
if (psys == NULL || state == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX currently makes a full copy of the state ... */
|
||||
BKE_nparticle_system_set_state(psys, state);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static struct PyMethodDef BPy_BPAR_methods[] = {
|
||||
{"new", (PyCFunction)bpy_bpar_new, METH_O, bpy_bpar_new_doc},
|
||||
{"copy", (PyCFunction)bpy_bpar_copy, METH_O, bpy_bpar_copy_doc},
|
||||
{"set_current_state", (PyCFunction)bpy_bpar_set_current_state, METH_VARARGS | METH_KEYWORDS, bpy_bpar_set_current_state_doc},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(BPy_BPAR_doc,
|
||||
"This module provides access to blenders particle data structures.\n"
|
||||
"\n"
|
||||
".. include:: include__bparticles.rst\n"
|
||||
);
|
||||
static struct PyModuleDef BPy_BPAR_module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"bparticles", /* m_name */
|
||||
BPy_BPAR_doc, /* m_doc */
|
||||
0, /* m_size */
|
||||
BPy_BPAR_methods, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
|
||||
PyObject *BPyInit_bparticles(void)
|
||||
{
|
||||
PyObject *mod;
|
||||
PyObject *submodule;
|
||||
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
|
||||
|
||||
BPy_BPAR_init_types();
|
||||
|
||||
mod = PyModule_Create(&BPy_BPAR_module_def);
|
||||
|
||||
/* bparticles.types */
|
||||
PyModule_AddObject(mod, "types", (submodule = BPyInit_bparticles_types()));
|
||||
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
|
||||
Py_INCREF(submodule);
|
||||
|
||||
return mod;
|
||||
}
|
35
source/blender/python/bparticles/bparticles_py_api.h
Normal file
35
source/blender/python/bparticles/bparticles_py_api.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/bparticles/bparticles_py_api.h
|
||||
* \ingroup pybparticles
|
||||
*/
|
||||
|
||||
#ifndef __BPARTICLES_PY_API_H__
|
||||
#define __BPARTICLES_PY_API_H__
|
||||
|
||||
PyObject *BPyInit_bparticles(void);
|
||||
|
||||
#endif /* __BPARTICLES_PY_API_H__ */
|
882
source/blender/python/bparticles/bparticles_py_types.c
Normal file
882
source/blender/python/bparticles/bparticles_py_types.c
Normal file
@@ -0,0 +1,882 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/bparticles/bparticles_py_types.c
|
||||
* \ingroup pybparticles
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_nparticle_types.h"
|
||||
|
||||
#include "BKE_nparticle.h"
|
||||
|
||||
#include "../mathutils/mathutils.h"
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include "bparticles_py_types.h" /* own include */
|
||||
|
||||
/* Type Docstrings
|
||||
* =============== */
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_state_doc,
|
||||
"Particle state data\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_attrstate_doc,
|
||||
"Particle attribute state data\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_attrstateseq_doc,
|
||||
"Particle attribute state sequence\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_attrstateiter_doc,
|
||||
"Iterator for looping over particle attribute states\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_particle_doc,
|
||||
"Single particle in state data\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_particleseq_doc,
|
||||
"Particle sequence\n"
|
||||
);
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_particleiter_doc,
|
||||
"Iterator for looping over particles\n"
|
||||
);
|
||||
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_state_attributes_doc,
|
||||
"State attributes (read-only).\n\n:type: :class:`NParticleAttributeStateSeq`"
|
||||
);
|
||||
static PyObject *bpy_bpar_state_attributes_get(BPy_NParticleState *self, void *UNUSED(closure))
|
||||
{
|
||||
return BPy_NParticleAttributeStateSeq_CreatePyObject(self->state);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_state_particles_doc,
|
||||
"Particles.\n\n:type: :class:`NParticleParticleSeq`"
|
||||
);
|
||||
static PyObject *bpy_bpar_state_particles_get(BPy_NParticleState *self, void *UNUSED(closure))
|
||||
{
|
||||
return BPy_NParticleParticleSeq_CreatePyObject(self->state);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_bpar_attrstate_name_doc,
|
||||
"Attribute name\n"
|
||||
);
|
||||
static PyObject *bpy_bpar_attrstate_name_get(BPy_NParticleAttributeState *self)
|
||||
{
|
||||
return PyUnicode_FromString(self->attrstate->desc.name);
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particle_dir(BPy_NParticleParticle *self)
|
||||
{
|
||||
NParticleAttributeStateIterator iter;
|
||||
PyObject *dict;
|
||||
PyObject *ret;
|
||||
PyObject *pystring;
|
||||
|
||||
// PYRNA_STRUCT_CHECK_OBJ(self);
|
||||
|
||||
dict = BPy_NParticleParticle_Type.tp_dict;
|
||||
if (dict)
|
||||
ret = PyDict_Keys(dict);
|
||||
else
|
||||
ret = PyList_New(0);
|
||||
|
||||
for (BKE_nparticle_state_attributes_begin(self->state, &iter);
|
||||
BKE_nparticle_state_attribute_iter_valid(&iter);
|
||||
BKE_nparticle_state_attribute_iter_next(&iter)) {
|
||||
pystring = PyUnicode_FromString(iter.attrstate->desc.name);
|
||||
PyList_Append(ret, pystring);
|
||||
Py_DECREF(pystring);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_state_repr(BPy_NParticleState *self)
|
||||
{
|
||||
NParticleState *state = self->state;
|
||||
|
||||
if (state) {
|
||||
return PyUnicode_FromFormat("<NParticleState(%p)>",
|
||||
state);
|
||||
}
|
||||
else {
|
||||
return PyUnicode_FromFormat("<NParticleState dead at %p>", self);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstate_repr(BPy_NParticleAttributeState *self)
|
||||
{
|
||||
NParticleAttributeState *attrstate = self->attrstate;
|
||||
|
||||
if (attrstate) {
|
||||
return PyUnicode_FromFormat("<NParticleAttributeState(%p) name=%s, datatype=%s>",
|
||||
attrstate, attrstate->desc.name,
|
||||
BKE_nparticle_datatype_name(attrstate->desc.datatype));
|
||||
}
|
||||
else {
|
||||
return PyUnicode_FromFormat("<NParticleAttributeState dead at %p>", self);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particle_repr(BPy_NParticleParticle *self)
|
||||
{
|
||||
NParticleIterator *iter = &self->iter;
|
||||
|
||||
if (iter->index >= 0) {
|
||||
return PyUnicode_FromFormat("<NParticleParticle index=%d>", iter->index);
|
||||
}
|
||||
else {
|
||||
return PyUnicode_FromFormat("<NParticleParticle invalid>");
|
||||
}
|
||||
}
|
||||
|
||||
static PyGetSetDef bpy_bpar_state_getseters[] = {
|
||||
{(char *)"attributes", (getter)bpy_bpar_state_attributes_get, (setter)NULL, (char *)bpy_bpar_state_attributes_doc, NULL},
|
||||
{(char *)"particles", (getter)bpy_bpar_state_particles_get, (setter)NULL, (char *)bpy_bpar_state_particles_doc, NULL},
|
||||
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyGetSetDef bpy_bpar_attrstate_getseters[] = {
|
||||
{(char *)"name", (getter)bpy_bpar_attrstate_name_get, (setter)NULL, (char *)bpy_bpar_attrstate_name_doc, NULL},
|
||||
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static struct PyMethodDef bpy_bpar_state_methods[] = {
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyMethodDef bpy_bpar_attrstate_methods[] = {
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyMethodDef bpy_bpar_particle_methods[] = {
|
||||
{"__dir__", (PyCFunction)bpy_bpar_particle_dir, METH_NOARGS, NULL},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static Py_hash_t bpy_bpar_state_hash(PyObject *self)
|
||||
{
|
||||
return _Py_HashPointer(((BPy_NParticleState *)self)->state);
|
||||
}
|
||||
|
||||
static Py_hash_t bpy_bpar_attrstate_hash(PyObject *self)
|
||||
{
|
||||
return _Py_HashPointer(((BPy_NParticleAttributeState *)self)->attrstate);
|
||||
}
|
||||
|
||||
|
||||
static Py_ssize_t bpy_bpar_attrstateseq_length(BPy_NParticleAttributeStateSeq *self)
|
||||
{
|
||||
return BKE_nparticle_state_num_attributes(self->state);
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstateseq_subscript_int(BPy_NParticleAttributeStateSeq *self, int keynum)
|
||||
{
|
||||
if (keynum < 0)
|
||||
keynum += BKE_nparticle_state_num_attributes(self->state);
|
||||
|
||||
if (keynum >= 0) {
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_get_attribute_by_index(self->state, keynum);
|
||||
if (attrstate)
|
||||
return BPy_NParticleAttributeState_CreatePyObject(self->state, attrstate);
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_IndexError,
|
||||
"NParticleAttributeStateSeq[index]: index %d out of range", keynum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstateseq_subscript_str(BPy_NParticleAttributeStateSeq *self, const char *keyname)
|
||||
{
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(self->state, keyname);
|
||||
|
||||
if (attrstate)
|
||||
return BPy_NParticleAttributeState_CreatePyObject(self->state, attrstate);
|
||||
|
||||
PyErr_Format(PyExc_KeyError, "NParticleAttributeStateSeq[key]: key \"%.200s\" not found", keyname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstateseq_subscript_slice(BPy_NParticleAttributeStateSeq *self, Py_ssize_t start, Py_ssize_t stop)
|
||||
{
|
||||
NParticleAttributeStateIterator iter;
|
||||
int count;
|
||||
|
||||
PyObject *list;
|
||||
PyObject *item;
|
||||
|
||||
list = PyList_New(0);
|
||||
|
||||
/* skip to start */
|
||||
for (count = 0, BKE_nparticle_state_attributes_begin(self->state, &iter);
|
||||
count < start && BKE_nparticle_state_attribute_iter_valid(&iter);
|
||||
++count, BKE_nparticle_state_attribute_iter_next(&iter))
|
||||
{}
|
||||
|
||||
/* add items until stop */
|
||||
for (; count < stop && BKE_nparticle_state_attribute_iter_valid(&iter);
|
||||
++count, BKE_nparticle_state_attribute_iter_next(&iter))
|
||||
{
|
||||
item = BPy_NParticleAttributeState_CreatePyObject(self->state, iter.attrstate);
|
||||
PyList_Append(list, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
BKE_nparticle_state_attribute_iter_end(&iter);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static int bpy_bpar_attrstateseq_contains(BPy_NParticleAttributeStateSeq *self, PyObject *value)
|
||||
{
|
||||
if (BPy_NParticleAttributeState_Check(value)) {
|
||||
BPy_NParticleAttributeState *attrstate_py = (BPy_NParticleAttributeState *)value;
|
||||
NParticleAttributeState *attrstate = attrstate_py->attrstate;
|
||||
if (BKE_nparticle_state_find_attribute(self->state, attrstate->desc.name) == attrstate)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstateseq_subscript(BPy_NParticleAttributeStateSeq *self, PyObject *key)
|
||||
{
|
||||
if (PyUnicode_Check(key)) {
|
||||
return bpy_bpar_attrstateseq_subscript_str(self, _PyUnicode_AsString(key));
|
||||
}
|
||||
else if (PyIndex_Check(key)) {
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
return bpy_bpar_attrstateseq_subscript_int(self, i);
|
||||
}
|
||||
else if (PySlice_Check(key)) {
|
||||
PySliceObject *key_slice = (PySliceObject *)key;
|
||||
Py_ssize_t step = 1;
|
||||
|
||||
if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
|
||||
return NULL;
|
||||
}
|
||||
else if (step != 1) {
|
||||
PyErr_SetString(PyExc_TypeError, "NParticleAttributeStateSeq[slice]: slice steps not supported");
|
||||
return NULL;
|
||||
}
|
||||
else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
|
||||
return bpy_bpar_attrstateseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
|
||||
}
|
||||
else {
|
||||
Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
|
||||
|
||||
/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
|
||||
if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
|
||||
if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
|
||||
|
||||
if (start < 0 || stop < 0) {
|
||||
/* only get the length for negative values */
|
||||
Py_ssize_t len = (Py_ssize_t)BKE_nparticle_state_num_attributes(self->state);
|
||||
if (start < 0) start += len;
|
||||
if (stop < 0) stop += len;
|
||||
}
|
||||
|
||||
if (stop - start <= 0) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
else {
|
||||
return bpy_bpar_attrstateseq_subscript_slice(self, start, stop);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"NParticleAttributeStateSeq[key]: invalid key, "
|
||||
"must be a string or an int, not %.200s",
|
||||
Py_TYPE(key)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PySequenceMethods bpy_bpar_attrstateseq_as_sequence = {
|
||||
(lenfunc)bpy_bpar_attrstateseq_length, /* sq_length */
|
||||
NULL, /* sq_concat */
|
||||
NULL, /* sq_repeat */
|
||||
(ssizeargfunc)bpy_bpar_attrstateseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
|
||||
NULL, /* sq_slice */
|
||||
(ssizeobjargproc)NULL, /* sq_ass_item */
|
||||
NULL, /* *was* sq_ass_slice */
|
||||
(objobjproc)bpy_bpar_attrstateseq_contains, /* sq_contains */
|
||||
(binaryfunc) NULL, /* sq_inplace_concat */
|
||||
(ssizeargfunc) NULL, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
static PyMappingMethods bpy_bpar_attrstateseq_as_mapping = {
|
||||
(lenfunc)bpy_bpar_attrstateseq_length, /* mp_length */
|
||||
(binaryfunc)bpy_bpar_attrstateseq_subscript, /* mp_subscript */
|
||||
(objobjargproc)NULL, /* mp_ass_subscript */
|
||||
};
|
||||
|
||||
static Py_ssize_t bpy_bpar_particleseq_length(BPy_NParticleAttributeStateSeq *self)
|
||||
{
|
||||
return BKE_nparticle_state_num_particles(self->state);
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particleseq_subscript_int(BPy_NParticleAttributeStateSeq *self, int keynum)
|
||||
{
|
||||
NParticleIterator iter;
|
||||
NParticleID id = (NParticleID)keynum;
|
||||
|
||||
BKE_nparticle_iter_from_id(self->state, &iter, id);
|
||||
return BPy_NParticleParticle_CreatePyObject(self->state, id, iter);
|
||||
}
|
||||
|
||||
static int bpy_bpar_particleseq_contains(BPy_NParticleParticleSeq *self, PyObject *value)
|
||||
{
|
||||
if (BPy_NParticleParticle_Check(value)) {
|
||||
BPy_NParticleParticle *particle_py = (BPy_NParticleParticle *)value;
|
||||
return particle_py->state == self->state && BKE_nparticle_iter_valid(&particle_py->iter);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particleseq_subscript(BPy_NParticleAttributeStateSeq *self, PyObject *key)
|
||||
{
|
||||
if (PyIndex_Check(key)) {
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
return bpy_bpar_particleseq_subscript_int(self, i);
|
||||
}
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"NParticleAttributeStateSeq[key]: invalid key, "
|
||||
"must be an int, not %.200s",
|
||||
Py_TYPE(key)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PySequenceMethods bpy_bpar_particleseq_as_sequence = {
|
||||
(lenfunc)bpy_bpar_particleseq_length, /* sq_length */
|
||||
NULL, /* sq_concat */
|
||||
NULL, /* sq_repeat */
|
||||
(ssizeargfunc)bpy_bpar_particleseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
|
||||
NULL, /* sq_slice */
|
||||
(ssizeobjargproc)NULL, /* sq_ass_item */
|
||||
NULL, /* *was* sq_ass_slice */
|
||||
(objobjproc)bpy_bpar_particleseq_contains, /* sq_contains */
|
||||
(binaryfunc) NULL, /* sq_inplace_concat */
|
||||
(ssizeargfunc) NULL, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
static PyMappingMethods bpy_bpar_particleseq_as_mapping = {
|
||||
(lenfunc)bpy_bpar_particleseq_length, /* mp_length */
|
||||
(binaryfunc)bpy_bpar_particleseq_subscript, /* mp_subscript */
|
||||
(objobjargproc)NULL, /* mp_ass_subscript */
|
||||
};
|
||||
|
||||
/* Iterator
|
||||
* -------- */
|
||||
|
||||
static PyObject *bpy_bpar_attrstateseq_iter(BPy_NParticleAttributeStateSeq *self)
|
||||
{
|
||||
BPy_NParticleAttributeStateIter *py_iter;
|
||||
|
||||
py_iter = (BPy_NParticleAttributeStateIter *)BPy_NParticleAttributeStateIter_CreatePyObject(self->state);
|
||||
BKE_nparticle_state_attributes_begin(self->state, &py_iter->iter);
|
||||
return (PyObject *)py_iter;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_attrstateiter_next(BPy_NParticleAttributeStateIter *self)
|
||||
{
|
||||
if (BKE_nparticle_state_attribute_iter_valid(&self->iter)) {
|
||||
PyObject *result = BPy_NParticleAttributeState_CreatePyObject(self->state, self->iter.attrstate);
|
||||
BKE_nparticle_state_attribute_iter_next(&self->iter);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
PyErr_SetNone(PyExc_StopIteration);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particleseq_iter(BPy_NParticleParticleSeq *self)
|
||||
{
|
||||
BPy_NParticleParticleIter *py_iter;
|
||||
|
||||
py_iter = (BPy_NParticleParticleIter *)BPy_NParticleParticleIter_CreatePyObject(self->state);
|
||||
BKE_nparticle_iter_init(self->state, &py_iter->iter);
|
||||
return (PyObject *)py_iter;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particleiter_next(BPy_NParticleParticleIter *self)
|
||||
{
|
||||
if (BKE_nparticle_iter_valid(&self->iter)) {
|
||||
NParticleID id = BKE_nparticle_iter_get_id(&self->iter);
|
||||
PyObject *result = BPy_NParticleParticle_CreatePyObject(self->state, id, self->iter);
|
||||
BKE_nparticle_iter_next(&self->iter);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
PyErr_SetNone(PyExc_StopIteration);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get/Set Functions
|
||||
* ================= */
|
||||
|
||||
static PyObject *bpy_bpar_particle_data_read(NParticleAttributeDescription *desc, void *data)
|
||||
{
|
||||
switch (desc->datatype) {
|
||||
case PAR_ATTR_DATATYPE_FLOAT:
|
||||
return PyFloat_FromDouble(*(float*)data);
|
||||
case PAR_ATTR_DATATYPE_INT:
|
||||
return PyLong_FromLong(*(int*)data);
|
||||
case PAR_ATTR_DATATYPE_BOOL:
|
||||
return PyBool_FromLong(*(bool*)data);
|
||||
case PAR_ATTR_DATATYPE_VECTOR:
|
||||
case PAR_ATTR_DATATYPE_POINT:
|
||||
case PAR_ATTR_DATATYPE_NORMAL:
|
||||
return Vector_CreatePyObject((float*)data, 3, Py_WRAP, NULL);
|
||||
case PAR_ATTR_DATATYPE_QUATERNION:
|
||||
return Quaternion_CreatePyObject((float*)data, Py_WRAP, NULL);
|
||||
case PAR_ATTR_DATATYPE_COLOR:
|
||||
return Color_CreatePyObject((float*)data, Py_WRAP, NULL);
|
||||
case PAR_ATTR_DATATYPE_MATRIX:
|
||||
return Matrix_CreatePyObject((float*)data, 4, 4, Py_WRAP, NULL);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bpy_bpar_particle_data_write(NParticleAttributeDescription *desc, void *data, PyObject *value)
|
||||
{
|
||||
/* XXX do we accept this sort of overhead just for error prints?
|
||||
* only needs to happen for actual errors, but mathutils_array_parse needs string in advance.
|
||||
*/
|
||||
// char error_prefix[128];
|
||||
// BLI_snprintf(error_prefix, sizeof(error_prefix), "NParticleParticle.%.200s", desc->name);
|
||||
|
||||
switch (desc->datatype) {
|
||||
case PAR_ATTR_DATATYPE_FLOAT:
|
||||
if (PyFloat_Check(value))
|
||||
*(float*)data = (float)PyFloat_AsDouble(value);
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"NParticleParticle.%.200s expects float, not %.200s",
|
||||
desc->name, Py_TYPE(value)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_INT:
|
||||
if (PyLong_Check(value))
|
||||
*(int*)data = (int)PyLong_AsLong(value);
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"NParticleParticle.%.200s expects int, not %.200s",
|
||||
desc->name, Py_TYPE(value)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_BOOL:
|
||||
if (PyBool_Check(value))
|
||||
*(bool*)data = (bool)PyLong_AsLong(value);
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"NParticleParticle.%.200s expects bool, not %.200s",
|
||||
desc->name, Py_TYPE(value)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case PAR_ATTR_DATATYPE_VECTOR:
|
||||
case PAR_ATTR_DATATYPE_POINT:
|
||||
case PAR_ATTR_DATATYPE_NORMAL: {
|
||||
if (mathutils_array_parse((float*)data, 3, 3, value, "NParticleParticle") == -1)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case PAR_ATTR_DATATYPE_QUATERNION: {
|
||||
if (mathutils_array_parse((float*)data, 4, 4, value, "NParticleParticle") == -1)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case PAR_ATTR_DATATYPE_COLOR: {
|
||||
if (mathutils_array_parse((float*)data, 3, 3, value, "NParticleParticle") == -1)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case PAR_ATTR_DATATYPE_MATRIX: {
|
||||
if (mathutils_array_parse((float*)data, 16, 16, value, "NParticleParticle") == -1)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *bpy_bpar_particle_getattro(BPy_NParticleParticle *self, PyObject *pyname)
|
||||
{
|
||||
const char *name = _PyUnicode_AsString(pyname);
|
||||
PyObject *ret;
|
||||
|
||||
// PYRNA_STRUCT_CHECK_OBJ(self);
|
||||
|
||||
if (name == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, "NParticleParticle: __getattr__ must be a string");
|
||||
ret = NULL;
|
||||
}
|
||||
else if (!BKE_nparticle_iter_valid(&self->iter)) {
|
||||
PyErr_Format(PyExc_AttributeError, "NParticleParticle: particle %d does not exist", self->id);
|
||||
ret = NULL;
|
||||
}
|
||||
else {
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(self->state, name);
|
||||
void *data;
|
||||
|
||||
if (!attrstate) {
|
||||
PyErr_Format(PyExc_AttributeError, "NParticleParticle.%.200s not found", name);
|
||||
ret = NULL;
|
||||
}
|
||||
else {
|
||||
data = BKE_nparticle_attribute_state_data(attrstate, self->iter.index);
|
||||
BLI_assert(data != NULL); /* the iterator is valid, so this should never happen */
|
||||
ret = bpy_bpar_particle_data_read(&attrstate->desc, data);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bpy_bpar_particle_setattro(BPy_NParticleParticle *self, PyObject *pyname, PyObject *value)
|
||||
{
|
||||
const char *name = _PyUnicode_AsString(pyname);
|
||||
|
||||
// PYRNA_STRUCT_CHECK_INT(self);
|
||||
|
||||
if (name == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, "NParticleParticle: __setattr__ must be a string");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(self->state, name);
|
||||
void *data;
|
||||
|
||||
if (!attrstate) {
|
||||
PyErr_Format(PyExc_AttributeError, "NParticleParticle.%.200s not found", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!BKE_nparticle_iter_valid(&self->iter)) {
|
||||
int index = BKE_nparticle_add(self->state, self->id);
|
||||
BKE_nparticle_iter_from_index(self->state, &self->iter, index);
|
||||
}
|
||||
|
||||
data = BKE_nparticle_attribute_state_data(attrstate, self->iter.index);
|
||||
if (!data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bpy_bpar_particle_data_write(&attrstate->desc, data, value) == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Dealloc Functions
|
||||
* ================= */
|
||||
|
||||
static void bpy_bpar_state_dealloc(BPy_NParticleState *self)
|
||||
{
|
||||
NParticleState *state = self->state;
|
||||
|
||||
if (state) {
|
||||
state->py_handle = NULL;
|
||||
|
||||
BKE_nparticle_state_free(state);
|
||||
}
|
||||
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_attrstate_dealloc(BPy_NParticleAttributeState *self)
|
||||
{
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_attrstateseq_dealloc(BPy_NParticleAttributeStateSeq *self)
|
||||
{
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_attrstateiter_dealloc(BPy_NParticleAttributeStateIter *self)
|
||||
{
|
||||
BKE_nparticle_state_attribute_iter_end(&self->iter);
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_particle_dealloc(BPy_NParticleParticle *self)
|
||||
{
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_particleseq_dealloc(BPy_NParticleParticleSeq *self)
|
||||
{
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static void bpy_bpar_particleiter_dealloc(BPy_NParticleParticleIter *self)
|
||||
{
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
/* Types
|
||||
* ===== */
|
||||
|
||||
PyTypeObject BPy_NParticleState_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleAttributeState_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleAttributeStateSeq_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleAttributeStateIter_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleParticle_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleParticleSeq_Type = {{{0}}};
|
||||
PyTypeObject BPy_NParticleParticleIter_Type = {{{0}}};
|
||||
|
||||
void BPy_BPAR_init_types(void)
|
||||
{
|
||||
BPy_NParticleState_Type.tp_basicsize = sizeof(BPy_NParticleState);
|
||||
BPy_NParticleAttributeState_Type.tp_basicsize = sizeof(BPy_NParticleAttributeState);
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_basicsize = sizeof(BPy_NParticleAttributeStateSeq);
|
||||
BPy_NParticleAttributeStateIter_Type.tp_basicsize = sizeof(BPy_NParticleAttributeStateIter);
|
||||
BPy_NParticleParticle_Type.tp_basicsize = sizeof(BPy_NParticleParticle);
|
||||
BPy_NParticleParticleSeq_Type.tp_basicsize = sizeof(BPy_NParticleParticleSeq);
|
||||
BPy_NParticleParticleIter_Type.tp_basicsize = sizeof(BPy_NParticleParticleIter);
|
||||
|
||||
BPy_NParticleState_Type.tp_name = "NParticleState";
|
||||
BPy_NParticleAttributeState_Type.tp_name = "NParticleAttributeState";
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_name = "NParticleAttributeStateSeq";
|
||||
BPy_NParticleAttributeStateIter_Type.tp_name = "NParticleAttributeStateIter";
|
||||
BPy_NParticleParticle_Type.tp_name = "NParticleParticle";
|
||||
BPy_NParticleParticleSeq_Type.tp_name = "NParticleParticleSeq";
|
||||
BPy_NParticleParticleIter_Type.tp_name = "NParticleParticleIter";
|
||||
|
||||
BPy_NParticleState_Type.tp_doc = bpy_bpar_state_doc;
|
||||
BPy_NParticleAttributeState_Type.tp_doc = bpy_bpar_attrstate_doc;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_doc = bpy_bpar_attrstateseq_doc;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_doc = bpy_bpar_attrstateiter_doc;
|
||||
BPy_NParticleParticle_Type.tp_doc = bpy_bpar_particle_doc;
|
||||
BPy_NParticleParticleSeq_Type.tp_doc = bpy_bpar_particleseq_doc;
|
||||
BPy_NParticleParticleIter_Type.tp_doc = bpy_bpar_particleiter_doc;
|
||||
|
||||
BPy_NParticleState_Type.tp_repr = (reprfunc)bpy_bpar_state_repr;
|
||||
BPy_NParticleAttributeState_Type.tp_repr = (reprfunc)bpy_bpar_attrstate_repr;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_repr = NULL;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_repr = NULL;
|
||||
BPy_NParticleParticle_Type.tp_repr = (reprfunc)bpy_bpar_particle_repr;
|
||||
BPy_NParticleParticleSeq_Type.tp_repr = NULL;
|
||||
BPy_NParticleParticleIter_Type.tp_repr = NULL;
|
||||
|
||||
BPy_NParticleState_Type.tp_getset = bpy_bpar_state_getseters;
|
||||
BPy_NParticleAttributeState_Type.tp_getset = bpy_bpar_attrstate_getseters;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_getset = NULL;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_getset = NULL;
|
||||
BPy_NParticleParticleSeq_Type.tp_getset = NULL;
|
||||
BPy_NParticleParticleIter_Type.tp_getset = NULL;
|
||||
|
||||
BPy_NParticleParticle_Type.tp_getattro = (getattrofunc)bpy_bpar_particle_getattro;
|
||||
BPy_NParticleParticle_Type.tp_setattro = (setattrofunc)bpy_bpar_particle_setattro;
|
||||
|
||||
BPy_NParticleState_Type.tp_methods = bpy_bpar_state_methods;
|
||||
BPy_NParticleAttributeState_Type.tp_methods = bpy_bpar_attrstate_methods;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_methods = NULL;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_methods = NULL;
|
||||
BPy_NParticleParticle_Type.tp_methods = bpy_bpar_particle_methods;
|
||||
BPy_NParticleParticleSeq_Type.tp_methods = NULL;
|
||||
BPy_NParticleParticleIter_Type.tp_methods = NULL;
|
||||
|
||||
BPy_NParticleState_Type.tp_hash = bpy_bpar_state_hash;
|
||||
BPy_NParticleAttributeState_Type.tp_hash = bpy_bpar_attrstate_hash;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_hash = NULL;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_hash = NULL;
|
||||
BPy_NParticleParticle_Type.tp_hash = NULL;
|
||||
BPy_NParticleParticleSeq_Type.tp_hash = NULL;
|
||||
BPy_NParticleParticleIter_Type.tp_hash = NULL;
|
||||
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_as_sequence = &bpy_bpar_attrstateseq_as_sequence;
|
||||
BPy_NParticleParticleSeq_Type.tp_as_sequence = &bpy_bpar_particleseq_as_sequence;
|
||||
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_as_mapping = &bpy_bpar_attrstateseq_as_mapping;
|
||||
BPy_NParticleParticleSeq_Type.tp_as_mapping = &bpy_bpar_particleseq_as_mapping;
|
||||
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_iter = (getiterfunc)bpy_bpar_attrstateseq_iter;
|
||||
BPy_NParticleParticleSeq_Type.tp_iter = (getiterfunc)bpy_bpar_particleseq_iter;
|
||||
|
||||
BPy_NParticleAttributeStateIter_Type.tp_iternext = (iternextfunc)bpy_bpar_attrstateiter_next;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_iter = PyObject_SelfIter;
|
||||
BPy_NParticleParticleIter_Type.tp_iternext = (iternextfunc)bpy_bpar_particleiter_next;
|
||||
BPy_NParticleParticleIter_Type.tp_iter = PyObject_SelfIter;
|
||||
|
||||
BPy_NParticleState_Type.tp_dealloc = (destructor)bpy_bpar_state_dealloc;
|
||||
BPy_NParticleAttributeState_Type.tp_dealloc = (destructor)bpy_bpar_attrstate_dealloc;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_dealloc = (destructor)bpy_bpar_attrstateseq_dealloc;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_dealloc = (destructor)bpy_bpar_attrstateiter_dealloc;
|
||||
BPy_NParticleParticle_Type.tp_dealloc = (destructor)bpy_bpar_particle_dealloc;
|
||||
BPy_NParticleParticleSeq_Type.tp_dealloc = (destructor)bpy_bpar_particleseq_dealloc;
|
||||
BPy_NParticleParticleIter_Type.tp_dealloc = (destructor)bpy_bpar_particleiter_dealloc;
|
||||
|
||||
BPy_NParticleState_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleAttributeState_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleAttributeStateSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleAttributeStateIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleParticle_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleParticleSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
BPy_NParticleParticleIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
|
||||
|
||||
PyType_Ready(&BPy_NParticleState_Type);
|
||||
PyType_Ready(&BPy_NParticleAttributeState_Type);
|
||||
PyType_Ready(&BPy_NParticleAttributeStateSeq_Type);
|
||||
PyType_Ready(&BPy_NParticleAttributeStateIter_Type);
|
||||
PyType_Ready(&BPy_NParticleParticle_Type);
|
||||
PyType_Ready(&BPy_NParticleParticleSeq_Type);
|
||||
PyType_Ready(&BPy_NParticleParticleIter_Type);
|
||||
}
|
||||
|
||||
|
||||
/* bparticles.types submodule
|
||||
* ********************* */
|
||||
|
||||
static struct PyModuleDef BPy_BPAR_types_module_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"bparticles.types", /* m_name */
|
||||
NULL, /* m_doc */
|
||||
0, /* m_size */
|
||||
NULL, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
|
||||
PyObject *BPyInit_bparticles_types(void)
|
||||
{
|
||||
PyObject *submodule;
|
||||
|
||||
submodule = PyModule_Create(&BPy_BPAR_types_module_def);
|
||||
|
||||
#define MODULE_TYPE_ADD(s, t) \
|
||||
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
|
||||
|
||||
/* bparticles_py_types.c */
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleState_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleAttributeState_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleAttributeStateSeq_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleAttributeStateIter_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleParticle_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleParticleSeq_Type);
|
||||
MODULE_TYPE_ADD(submodule, BPy_NParticleParticleIter_Type);
|
||||
|
||||
#undef MODULE_TYPE_ADD
|
||||
|
||||
return submodule;
|
||||
}
|
||||
|
||||
|
||||
/* Utility Functions
|
||||
* ***************** */
|
||||
|
||||
PyObject *BPy_NParticleState_CreatePyObject(NParticleState *state)
|
||||
{
|
||||
BPy_NParticleState *self;
|
||||
|
||||
if (state->py_handle) {
|
||||
self = state->py_handle;
|
||||
Py_INCREF(self);
|
||||
}
|
||||
else {
|
||||
self = PyObject_New(BPy_NParticleState, &BPy_NParticleState_Type);
|
||||
self->state = state;
|
||||
|
||||
state->py_handle = self; /* point back */
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleAttributeState_CreatePyObject(NParticleState *state, NParticleAttributeState *attr)
|
||||
{
|
||||
BPy_NParticleAttributeState *self = PyObject_New(BPy_NParticleAttributeState, &BPy_NParticleAttributeState_Type);
|
||||
self->state = state;
|
||||
self->attrstate = attr;
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleAttributeStateSeq_CreatePyObject(NParticleState *state)
|
||||
{
|
||||
BPy_NParticleAttributeStateSeq *self = PyObject_New(BPy_NParticleAttributeStateSeq, &BPy_NParticleAttributeStateSeq_Type);
|
||||
self->state = state;
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleAttributeStateIter_CreatePyObject(NParticleState *state)
|
||||
{
|
||||
BPy_NParticleAttributeStateIter *self = PyObject_New(BPy_NParticleAttributeStateIter, &BPy_NParticleAttributeStateIter_Type);
|
||||
self->state = state;
|
||||
/* caller must initialize 'iter' member */
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleParticle_CreatePyObject(NParticleState *state, NParticleID id, NParticleIterator iter)
|
||||
{
|
||||
BPy_NParticleParticle *self = PyObject_New(BPy_NParticleParticle, &BPy_NParticleParticle_Type);
|
||||
self->state = state;
|
||||
self->id = id;
|
||||
self->iter = iter;
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleParticleSeq_CreatePyObject(NParticleState *state)
|
||||
{
|
||||
BPy_NParticleParticleSeq *self = PyObject_New(BPy_NParticleParticleSeq, &BPy_NParticleParticleSeq_Type);
|
||||
self->state = state;
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyObject *BPy_NParticleParticleIter_CreatePyObject(NParticleState *state)
|
||||
{
|
||||
BPy_NParticleParticleIter *self = PyObject_New(BPy_NParticleParticleIter, &BPy_NParticleParticleIter_Type);
|
||||
self->state = state;
|
||||
/* caller must initialize 'iter' member */
|
||||
return (PyObject *)self;
|
||||
}
|
101
source/blender/python/bparticles/bparticles_py_types.h
Normal file
101
source/blender/python/bparticles/bparticles_py_types.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2013 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Lukas Toenne
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/python/bparticles/bparticles_py_types.h
|
||||
* \ingroup pybparticles
|
||||
*/
|
||||
|
||||
#ifndef __BPARTICLES_PY_TYPES_H__
|
||||
#define __BPARTICLES_PY_TYPES_H__
|
||||
|
||||
extern PyTypeObject BPy_NParticleState_Type;
|
||||
extern PyTypeObject BPy_NParticleAttributeState_Type;
|
||||
extern PyTypeObject BPy_NParticleAttributeStateSeq_Type;
|
||||
extern PyTypeObject BPy_NParticleAttributeStateIter_Type;
|
||||
extern PyTypeObject BPy_NParticleParticle_Type;
|
||||
extern PyTypeObject BPy_NParticleParticleSeq_Type;
|
||||
extern PyTypeObject BPy_NParticleParticleIter_Type;
|
||||
|
||||
#define BPy_NParticleState_Check(v) (Py_TYPE(v) == &BPy_NParticleState_Type)
|
||||
#define BPy_NParticleAttributeState_Check(v) (Py_TYPE(v) == &BPy_NParticleAttributeState_Type)
|
||||
#define BPy_NParticleAttributeStateSeq_Check(v) (Py_TYPE(v) == &BPy_NParticleAttributeStateSeq_Type)
|
||||
#define BPy_NParticleAttributeStateIter_Check(v) (Py_TYPE(v) == &BPy_NParticleAttributeStateIter_Type)
|
||||
#define BPy_NParticleParticle_Check(v) (Py_TYPE(v) == &BPy_NParticleParticle_Type)
|
||||
#define BPy_NParticleParticleSeq_Check(v) (Py_TYPE(v) == &BPy_NParticleParticleSeq_Type)
|
||||
#define BPy_NParticleParticleIter_Check(v) (Py_TYPE(v) == &BPy_NParticleParticleIter_Type)
|
||||
|
||||
typedef struct BPy_NParticleState {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
} BPy_NParticleState;
|
||||
|
||||
typedef struct BPy_NParticleAttributeState {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
struct NParticleAttributeState *attrstate;
|
||||
} BPy_NParticleAttributeState;
|
||||
|
||||
typedef struct BPy_NParticleAttributeStateSeq {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
} BPy_NParticleAttributeStateSeq;
|
||||
|
||||
typedef struct BPy_NParticleAttributeStateIter {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
NParticleAttributeStateIterator iter;
|
||||
} BPy_NParticleAttributeStateIter;
|
||||
|
||||
typedef struct BPy_NParticleParticle {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
NParticleID id;
|
||||
NParticleIterator iter;
|
||||
} BPy_NParticleParticle;
|
||||
|
||||
typedef struct BPy_NParticleParticleSeq {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
} BPy_NParticleParticleSeq;
|
||||
|
||||
typedef struct BPy_NParticleParticleIter {
|
||||
PyObject_VAR_HEAD
|
||||
struct NParticleState *state; /* keep first */
|
||||
NParticleIterator iter;
|
||||
} BPy_NParticleParticleIter;
|
||||
|
||||
void BPy_BPAR_init_types(void);
|
||||
|
||||
PyObject *BPyInit_bparticles_types(void);
|
||||
|
||||
PyObject *BPy_NParticleState_CreatePyObject(NParticleState *state);
|
||||
PyObject *BPy_NParticleAttributeState_CreatePyObject(NParticleState *state, NParticleAttributeState *attr);
|
||||
PyObject *BPy_NParticleAttributeStateSeq_CreatePyObject(NParticleState *state);
|
||||
PyObject *BPy_NParticleAttributeStateIter_CreatePyObject(NParticleState *state);
|
||||
PyObject *BPy_NParticleParticle_CreatePyObject(NParticleState *state, NParticleID id, NParticleIterator iter);
|
||||
PyObject *BPy_NParticleParticleSeq_CreatePyObject(NParticleState *state);
|
||||
PyObject *BPy_NParticleParticleIter_CreatePyObject(NParticleState *state);
|
||||
|
||||
#endif /* __BPARTICLES_PY_TYPES_H__ */
|
@@ -80,6 +80,7 @@
|
||||
#include "../generic/blf_py_api.h"
|
||||
#include "../generic/idprop_py_api.h"
|
||||
#include "../bmesh/bmesh_py_api.h"
|
||||
#include "../bparticles/bparticles_py_api.h"
|
||||
#include "../mathutils/mathutils.h"
|
||||
|
||||
|
||||
@@ -227,6 +228,7 @@ static struct _inittab bpy_internal_modules[] = {
|
||||
{"bmesh.utils", BPyInit_bmesh_utils},
|
||||
{"bmesh.utils", BPyInit_bmesh_geometry},
|
||||
#endif
|
||||
{(char *)"bparticles", BPyInit_bparticles},
|
||||
#ifdef WITH_AUDASPACE
|
||||
{"aud", AUD_initPython},
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user