forked from bartvdbraak/blender
General particle bug fixes + few small goodies
The goodies: * Curves can be used as normal dynamic effectors too with the new "curve" field shape. * Group visualization has optional duplication counts for each object in the specified group. * Object & group visualizations, which are done without taking the dupliobject's global position into account (unless the whole group is used). This is much nicer than the previous behavior, but I added a "Use Global Location" option for those who want to use it the old way. * The active particle system's particles are now drawn a with theme coloured outline instead of pure white. * Added object aligned velocity factors (buttons categorized and re-organized too). Bug fixes: * Absorption didn't work as the ui toggle button was forgotten. * Some other force field ui tweaks. * Crash after adding children and changing trails count. * Display types "cross" and "axis" crashed. * Particles weren't drawn with correct coloring. * Billboards didn't update properly in viewport to camera location changes. * Particle rotation wasn't recreated correctly from point cache. * Changing particles amount crashed sometimes. * Some files with child hair crashed on loading. * Compiler warning fixes. * Adding boids crashed on frame 1;
This commit is contained in:
parent
a344977147
commit
3816554cbc
@ -121,17 +121,19 @@ class PARTICLE_PT_emission(ParticleButtonsPanel):
|
||||
layout.enabled = particle_panel_enabled(psys) and not psys.multiple_caches
|
||||
|
||||
row = layout.row()
|
||||
row.active = part.distribution != 'GRID'
|
||||
row.itemR(part, "amount")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column(align=True)
|
||||
col.itemR(part, "start")
|
||||
col.itemR(part, "end")
|
||||
if part.type != 'HAIR':
|
||||
split = layout.split()
|
||||
|
||||
col = split.column(align=True)
|
||||
col.itemR(part, "start")
|
||||
col.itemR(part, "end")
|
||||
|
||||
col = split.column(align=True)
|
||||
col.itemR(part, "lifetime")
|
||||
col.itemR(part, "random_lifetime", slider=True)
|
||||
col = split.column(align=True)
|
||||
col.itemR(part, "lifetime")
|
||||
col.itemR(part, "random_lifetime", slider=True)
|
||||
|
||||
layout.row().itemL(text="Emit From:")
|
||||
|
||||
@ -221,7 +223,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
|
||||
|
||||
point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0)
|
||||
|
||||
class PARTICLE_PT_initial(ParticleButtonsPanel):
|
||||
class PARTICLE_PT_velocity(ParticleButtonsPanel):
|
||||
__label__ = "Velocity"
|
||||
|
||||
def poll(self, context):
|
||||
@ -238,48 +240,66 @@ class PARTICLE_PT_initial(ParticleButtonsPanel):
|
||||
part = psys.settings
|
||||
|
||||
layout.enabled = particle_panel_enabled(psys)
|
||||
|
||||
layout.row().itemL(text="Direction:")
|
||||
|
||||
split = layout.split()
|
||||
|
||||
sub = split.column()
|
||||
sub.itemL(text="Emitter Geometry:")
|
||||
sub.itemR(part, "normal_factor")
|
||||
subsub = sub.column(align=True)
|
||||
subsub.itemR(part, "tangent_factor")
|
||||
subsub.itemR(part, "tangent_phase", slider=True)
|
||||
|
||||
sub = split.column()
|
||||
sub.itemL(text="Emitter Object")
|
||||
sub.itemR(part, "object_aligned_factor", text="")
|
||||
|
||||
layout.row().itemL(text="Other:")
|
||||
split = layout.split()
|
||||
sub = split.column()
|
||||
if part.emit_from=='PARTICLE':
|
||||
sub.itemR(part, "particle_factor")
|
||||
else:
|
||||
sub.itemR(part, "object_factor", slider=True)
|
||||
sub = split.column()
|
||||
sub.itemR(part, "random_factor")
|
||||
sub.itemR(part, "tangent_factor")
|
||||
sub.itemR(part, "tangent_phase", slider=True)
|
||||
|
||||
sub = split.column()
|
||||
sub.itemL(text="TODO:")
|
||||
sub.itemL(text="Object aligned")
|
||||
sub.itemL(text="direction: X, Y, Z")
|
||||
#if part.type=='REACTOR':
|
||||
# sub.itemR(part, "reactor_factor")
|
||||
# sub.itemR(part, "reaction_shape", slider=True)
|
||||
|
||||
if part.type=='REACTOR':
|
||||
sub.itemR(part, "reactor_factor")
|
||||
sub.itemR(part, "reaction_shape", slider=True)
|
||||
class PARTICLE_PT_rotation(ParticleButtonsPanel):
|
||||
__label__ = "Rotation"
|
||||
|
||||
def poll(self, context):
|
||||
if particle_panel_poll(context):
|
||||
psys = context.particle_system
|
||||
return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
|
||||
else:
|
||||
sub.itemL(text="")
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
|
||||
layout.row().itemL(text="Rotation:")
|
||||
layout.enabled = particle_panel_enabled(psys)
|
||||
|
||||
split = layout.split()
|
||||
split.itemL(text="Initial Rotation:")
|
||||
split.itemR(part, "rotation_dynamic")
|
||||
split = layout.split()
|
||||
|
||||
sub = split.column()
|
||||
|
||||
sub.itemR(part, "rotation_mode", text="Axis")
|
||||
split = layout.split()
|
||||
sub = split.column(align=True)
|
||||
sub.itemR(part, "rotation_mode", text="")
|
||||
sub.itemR(part, "random_rotation_factor", slider=True, text="Random")
|
||||
|
||||
sub = split.column()
|
||||
sub.itemR(part, "rotation_dynamic")
|
||||
sub.itemR(part, "random_rotation_factor", slider=True)
|
||||
sub = split.column()
|
||||
sub = split.column(align=True)
|
||||
sub.itemR(part, "phase_factor", slider=True)
|
||||
sub.itemR(part, "random_phase_factor", text="Random", slider=True)
|
||||
|
||||
layout.row().itemL(text="Angular velocity:")
|
||||
layout.row().itemL(text="Angular Velocity:")
|
||||
layout.row().itemR(part, "angular_velocity_mode", expand=True)
|
||||
split = layout.split()
|
||||
|
||||
@ -607,16 +627,37 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
|
||||
|
||||
elif part.ren_as == 'OBJECT':
|
||||
sub.itemR(part, "dupli_object")
|
||||
sub.itemR(part, "use_global_dupli")
|
||||
elif part.ren_as == 'GROUP':
|
||||
sub.itemR(part, "dupli_group")
|
||||
split = layout.split()
|
||||
sub = split.column()
|
||||
sub.itemR(part, "whole_group")
|
||||
colsub = sub.column()
|
||||
colsub.active = part.whole_group == False
|
||||
colsub.itemR(part, "use_group_count")
|
||||
|
||||
sub = split.column()
|
||||
colsub = sub.column()
|
||||
colsub.active = part.whole_group == False
|
||||
colsub.itemR(part, "use_global_dupli")
|
||||
colsub.itemR(part, "rand_group")
|
||||
|
||||
if part.use_group_count and not part.whole_group:
|
||||
row = layout.row()
|
||||
row.template_list(part, "dupliweights", part, "active_dupliweight_index")
|
||||
|
||||
col = row.column()
|
||||
subrow = col.row()
|
||||
subcol = subrow.column(align=True)
|
||||
subcol.itemO("particle.dupliob_move_up", icon='VICON_MOVE_UP', text="")
|
||||
subcol.itemO("particle.dupliob_move_down", icon='VICON_MOVE_DOWN', text="")
|
||||
|
||||
weight = part.active_dupliweight
|
||||
if weight:
|
||||
row = layout.row()
|
||||
row.itemR(weight, "count")
|
||||
|
||||
elif part.ren_as == 'BILLBOARD':
|
||||
sub.itemL(text="Align:")
|
||||
|
||||
@ -898,7 +939,8 @@ bpy.types.register(PARTICLE_PT_particles)
|
||||
bpy.types.register(PARTICLE_PT_hair_dynamics)
|
||||
bpy.types.register(PARTICLE_PT_cache)
|
||||
bpy.types.register(PARTICLE_PT_emission)
|
||||
bpy.types.register(PARTICLE_PT_initial)
|
||||
bpy.types.register(PARTICLE_PT_velocity)
|
||||
bpy.types.register(PARTICLE_PT_rotation)
|
||||
bpy.types.register(PARTICLE_PT_physics)
|
||||
bpy.types.register(PARTICLE_PT_boidbrain)
|
||||
bpy.types.register(PARTICLE_PT_render)
|
||||
|
@ -78,7 +78,7 @@ def effector_weights_ui(self, weights):
|
||||
layout.itemS()
|
||||
|
||||
flow = layout.column_flow()
|
||||
flow.itemR(weights, "spherical", slider=True)
|
||||
flow.itemR(weights, "force", slider=True)
|
||||
flow.itemR(weights, "vortex", slider=True)
|
||||
flow.itemR(weights, "magnetic", slider=True)
|
||||
flow.itemR(weights, "wind", slider=True)
|
||||
@ -110,7 +110,7 @@ def basic_force_field_settings_ui(self, field):
|
||||
col.itemR(field, "flow")
|
||||
elif field.type == 'HARMONIC':
|
||||
col.itemR(field, "harmonic_damping", text="Damping")
|
||||
elif field.type == 'VORTEX' and field.shape == 'PLANE':
|
||||
elif field.type == 'VORTEX' and field.shape != 'POINT':
|
||||
col.itemR(field, "inflow")
|
||||
elif field.type == 'DRAG':
|
||||
col.itemR(field, "quadratic_drag", text="Quadratic")
|
||||
@ -140,6 +140,7 @@ def basic_force_field_falloff_ui(self, field):
|
||||
col.itemR(field, "z_direction", text="")
|
||||
col.itemR(field, "use_min_distance", text="Use Minimum")
|
||||
col.itemR(field, "use_max_distance", text="Use Maximum")
|
||||
col.itemR(field, "do_absorption")
|
||||
|
||||
col = split.column()
|
||||
col.itemR(field, "falloff_power", text="Power")
|
||||
|
@ -57,6 +57,7 @@ typedef struct BVHTreeFromMesh
|
||||
|
||||
/* Vertex array, so that callbacks have instante access to data */
|
||||
struct MVert *vert;
|
||||
struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */
|
||||
struct MFace *face;
|
||||
|
||||
/* radius for raycast */
|
||||
@ -96,6 +97,8 @@ BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMes
|
||||
*/
|
||||
BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
|
||||
|
||||
BVHTree* bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
|
||||
|
||||
/*
|
||||
* Frees data allocated by a call to bvhtree_from_mesh_*.
|
||||
*/
|
||||
@ -109,6 +112,7 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
|
||||
//Using local coordinates
|
||||
#define BVHTREE_FROM_FACES 0
|
||||
#define BVHTREE_FROM_VERTICES 1
|
||||
#define BVHTREE_FROM_EDGES 2
|
||||
|
||||
typedef LinkNode* BVHCache;
|
||||
|
||||
|
@ -138,6 +138,7 @@ int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struc
|
||||
/* EffectedPoint->flag */
|
||||
#define PE_WIND_AS_SPEED 1
|
||||
#define PE_DYNAMIC_ROTATION 2
|
||||
#define PE_USE_NORMAL_DATA 4
|
||||
|
||||
/* EffectorData->flag */
|
||||
#define PE_VELOCITY_TO_IMPULSE 1
|
||||
|
@ -201,6 +201,8 @@ struct Object *psys_get_lattice(struct ParticleSimulationData *sim);
|
||||
int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
|
||||
int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
|
||||
|
||||
void psys_check_group_weights(struct ParticleSettings *part);
|
||||
|
||||
/* free */
|
||||
void psys_free_settings(struct ParticleSettings *part);
|
||||
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
|
||||
|
@ -776,6 +776,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
||||
GroupObject *go;
|
||||
Object *ob=0, **oblist=0, obcopy, *obcopylist=0;
|
||||
DupliObject *dob;
|
||||
ParticleDupliWeight *dw;
|
||||
ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)};
|
||||
ParticleSettings *part;
|
||||
ParticleData *pa;
|
||||
@ -783,7 +784,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
||||
ParticleKey state;
|
||||
ParticleCacheKey *cache;
|
||||
float ctime, pa_time, scale = 1.0f;
|
||||
float tmat[4][4], mat[4][4], pamat[4][4], size=0.0;
|
||||
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0;
|
||||
float (*obmat)[4], (*oldobmat)[4];
|
||||
int lay, a, b, counter, hair = 0;
|
||||
int totpart, totchild, totgroup=0, pa_num;
|
||||
@ -813,6 +814,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
||||
((part->ren_as == PART_DRAW_OB && part->dup_ob) ||
|
||||
(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) {
|
||||
|
||||
psys_check_group_weights(part);
|
||||
|
||||
/* if we have a hair particle system, use the path cache */
|
||||
if(part->type == PART_HAIR) {
|
||||
if(psys->flag & PSYS_HAIR_DONE)
|
||||
@ -831,18 +834,37 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
||||
if(part->ren_as==PART_DRAW_GR) {
|
||||
group_handle_recalc_and_update(scene, par, part->dup_group);
|
||||
|
||||
for(go=part->dup_group->gobject.first; go; go=go->next)
|
||||
totgroup++;
|
||||
if(part->draw & PART_DRAW_COUNT_GR) {
|
||||
for(dw=part->dupliweights.first; dw; dw=dw->next)
|
||||
totgroup += dw->count;
|
||||
}
|
||||
else {
|
||||
for(go=part->dup_group->gobject.first; go; go=go->next)
|
||||
totgroup++;
|
||||
}
|
||||
|
||||
/* we also copy the actual objects to restore afterwards, since
|
||||
* where_is_object_time will change the object which breaks transform */
|
||||
oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list");
|
||||
obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list");
|
||||
|
||||
go = part->dup_group->gobject.first;
|
||||
for(a=0; a<totgroup; a++, go=go->next) {
|
||||
oblist[a] = go->ob;
|
||||
obcopylist[a] = *go->ob;
|
||||
|
||||
if(part->draw & PART_DRAW_COUNT_GR && totgroup) {
|
||||
dw = part->dupliweights.first;
|
||||
|
||||
for(a=0; a<totgroup; dw=dw->next) {
|
||||
for(b=0; b<dw->count; b++, a++) {
|
||||
oblist[a] = dw->ob;
|
||||
obcopylist[a] = *dw->ob;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
go = part->dup_group->gobject.first;
|
||||
for(a=0; a<totgroup; a++, go=go->next) {
|
||||
oblist[a] = go->ob;
|
||||
obcopylist[a] = *go->ob;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -936,11 +958,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
|
||||
else {
|
||||
/* to give ipos in object correct offset */
|
||||
where_is_object_time(scene, ob, ctime-pa_time);
|
||||
|
||||
VECCOPY(vec, obmat[3]);
|
||||
obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
|
||||
|
||||
Mat4CpyMat4(mat, pamat);
|
||||
|
||||
Mat4MulMat4(tmat, obmat, mat);
|
||||
Mat4MulFloat3((float *)tmat, size*scale);
|
||||
|
||||
if(part->draw & PART_DRAW_GLOBAL_OB)
|
||||
VECADD(tmat[3], tmat[3], vec);
|
||||
|
||||
if(par_space_mat)
|
||||
Mat4MulMat4(mat, tmat, par_space_mat);
|
||||
else
|
||||
|
@ -73,13 +73,11 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
|
||||
{
|
||||
BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule;
|
||||
BoidSettings *boids = bbd->part->boids;
|
||||
Object *priority_ob = NULL;
|
||||
BoidParticle *bpa = pa->boid;
|
||||
EffectedPoint epoint;
|
||||
ListBase *effectors = bbd->sim->psys->effectors;
|
||||
EffectorCache *cur, *eff = NULL;
|
||||
EffectorData efd, cur_efd;
|
||||
float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
|
||||
float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
|
||||
float priority = 0.0f, len = 0.0f;
|
||||
int ret = 0;
|
||||
@ -1051,9 +1049,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
|
||||
float wanted_dir[3];
|
||||
float q[4], mat[3][3]; /* rotation */
|
||||
float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
|
||||
float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f};
|
||||
float force[3] = {0.0f, 0.0f, 0.0f};
|
||||
float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;
|
||||
int p = pa - bbd->sim->psys->particles;
|
||||
|
||||
set_boid_values(&val, boids, pa);
|
||||
|
||||
|
@ -479,6 +479,32 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r
|
||||
} while(t2);
|
||||
}
|
||||
|
||||
// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges.
|
||||
// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
|
||||
static void mesh_edges_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest)
|
||||
{
|
||||
const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata;
|
||||
MVert *vert = data->vert;
|
||||
MEdge *edge = data->edge + index;
|
||||
float nearest_tmp[3], dist;
|
||||
|
||||
float *t0, *t1;
|
||||
t0 = vert[ edge->v1 ].co;
|
||||
t1 = vert[ edge->v2 ].co;
|
||||
|
||||
PclosestVL3Dfl(nearest_tmp, co, t0, t1);
|
||||
dist = VecLenf(nearest_tmp, co);
|
||||
|
||||
if(dist < nearest->dist)
|
||||
{
|
||||
nearest->index = index;
|
||||
nearest->dist = dist;
|
||||
VECCOPY(nearest->co, nearest_tmp);
|
||||
VecSubf(nearest->no, t0, t1);
|
||||
Normalize(nearest->no);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BVH builders
|
||||
*/
|
||||
@ -605,6 +631,68 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float
|
||||
|
||||
}
|
||||
|
||||
// Builds a bvh tree.. where nodes are the faces of the given mesh.
|
||||
BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis)
|
||||
{
|
||||
BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES);
|
||||
|
||||
//Not in cache
|
||||
if(tree == NULL)
|
||||
{
|
||||
int i;
|
||||
int numEdges= mesh->getNumEdges(mesh);
|
||||
MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT);
|
||||
MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
|
||||
|
||||
if(vert != NULL && edge != NULL)
|
||||
{
|
||||
/* Create a bvh-tree of the given target */
|
||||
tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
|
||||
if(tree != NULL)
|
||||
{
|
||||
for(i = 0; i < numEdges; i++)
|
||||
{
|
||||
float co[4][3];
|
||||
VECCOPY(co[0], vert[ edge[i].v1 ].co);
|
||||
VECCOPY(co[1], vert[ edge[i].v2 ].co);
|
||||
|
||||
BLI_bvhtree_insert(tree, i, co[0], 2);
|
||||
}
|
||||
BLI_bvhtree_balance(tree);
|
||||
|
||||
//Save on cache for later use
|
||||
// printf("BVHTree built and saved on cache\n");
|
||||
bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("BVHTree is already build, using cached tree\n");
|
||||
}
|
||||
|
||||
|
||||
//Setup BVHTreeFromMesh
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->tree = tree;
|
||||
|
||||
if(data->tree)
|
||||
{
|
||||
data->cached = TRUE;
|
||||
|
||||
data->nearest_callback = mesh_edges_nearest_point;
|
||||
data->raycast_callback = NULL;
|
||||
|
||||
data->mesh = mesh;
|
||||
data->vert = mesh->getVertDataArray(mesh, CD_MVERT);
|
||||
data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE);
|
||||
|
||||
data->sphere_radius = epsilon;
|
||||
}
|
||||
return data->tree;
|
||||
|
||||
}
|
||||
|
||||
// Frees data allocated by a call to bvhtree_from_mesh_*.
|
||||
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
|
||||
{
|
||||
|
@ -228,6 +228,8 @@ static void precalculate_effector(EffectorCache *eff)
|
||||
}
|
||||
else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) {
|
||||
eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface );
|
||||
if(eff->ob->type == OB_CURVE)
|
||||
eff->flag |= PE_USE_NORMAL_DATA;
|
||||
}
|
||||
else if(eff->psys)
|
||||
psys_update_particle_tree(eff->psys, eff->scene->r.cfra);
|
||||
@ -518,7 +520,7 @@ float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *poi
|
||||
float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f;
|
||||
float fac, r_fac;
|
||||
|
||||
fac = Inpf(efd->nor, efd->vec_to_point);
|
||||
fac = Inpf(efd->nor, efd->vec_to_point2);
|
||||
|
||||
if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f)
|
||||
falloff=0.0f;
|
||||
@ -691,10 +693,16 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
|
||||
VecSubf(efd->vec_to_point, point->loc, efd->loc);
|
||||
efd->distance = VecLength(efd->vec_to_point);
|
||||
|
||||
/* for some effectors we need the object center every time */
|
||||
VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
|
||||
VECCOPY(efd->nor2, eff->ob->obmat[2]);
|
||||
Normalize(efd->nor2);
|
||||
if(eff->flag & PE_USE_NORMAL_DATA) {
|
||||
VECCOPY(efd->vec_to_point2, efd->vec_to_point);
|
||||
VECCOPY(efd->nor2, efd->nor);
|
||||
}
|
||||
else {
|
||||
/* for some effectors we need the object center every time */
|
||||
VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]);
|
||||
VECCOPY(efd->nor2, eff->ob->obmat[2]);
|
||||
Normalize(efd->nor2);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -835,8 +843,7 @@ void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *
|
||||
|
||||
switch(pd->forcefield){
|
||||
case PFIELD_WIND:
|
||||
Normalize(force);
|
||||
strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f);
|
||||
VECCOPY(force, efd->nor);
|
||||
VecMulf(force, strength * efd->falloff);
|
||||
break;
|
||||
case PFIELD_FORCE:
|
||||
|
@ -6211,7 +6211,8 @@ static void surfaceModifier_freeData(ModifierData *md)
|
||||
MEM_freeN(surmd->bvhtree);
|
||||
}
|
||||
|
||||
surmd->dm->release(surmd->dm);
|
||||
if(surmd->dm)
|
||||
surmd->dm->release(surmd->dm);
|
||||
|
||||
if(surmd->x)
|
||||
MEM_freeN(surmd->x);
|
||||
@ -6298,7 +6299,10 @@ static void surfaceModifier_deformVerts(
|
||||
else
|
||||
surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh");
|
||||
|
||||
bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
|
||||
if(surmd->dm->getNumFaces(surmd->dm))
|
||||
bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
|
||||
else
|
||||
bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_boid_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
#include "DNA_particle_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@ -63,6 +64,7 @@
|
||||
#include "BKE_cloth.h"
|
||||
#include "BKE_effect.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_group.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_lattice.h"
|
||||
#include "BKE_utildefines.h"
|
||||
@ -296,6 +298,60 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void psys_check_group_weights(ParticleSettings *part)
|
||||
{
|
||||
ParticleDupliWeight *dw, *tdw;
|
||||
GroupObject *go;
|
||||
int current = 0;
|
||||
|
||||
if(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
|
||||
/* first remove all weights that don't have an object in the group */
|
||||
dw = part->dupliweights.first;
|
||||
while(dw) {
|
||||
if(!object_in_group(dw->ob, part->dup_group)) {
|
||||
tdw = dw->next;
|
||||
BLI_freelinkN(&part->dupliweights, dw);
|
||||
dw = tdw;
|
||||
}
|
||||
else
|
||||
dw = dw->next;
|
||||
}
|
||||
|
||||
/* then add objects in the group to new list */
|
||||
go = part->dup_group->gobject.first;
|
||||
while(go) {
|
||||
dw = part->dupliweights.first;
|
||||
while(dw && dw->ob != go->ob)
|
||||
dw = dw->next;
|
||||
|
||||
if(!dw) {
|
||||
dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
|
||||
dw->ob = go->ob;
|
||||
dw->count = 1;
|
||||
BLI_addtail(&part->dupliweights, dw);
|
||||
}
|
||||
|
||||
go = go->next;
|
||||
}
|
||||
|
||||
dw = part->dupliweights.first;
|
||||
for(; dw; dw=dw->next) {
|
||||
if(dw->flag & PART_DUPLIW_CURRENT) {
|
||||
current = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!current) {
|
||||
dw = part->dupliweights.first;
|
||||
if(dw)
|
||||
dw->flag |= PART_DUPLIW_CURRENT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BLI_freelistN(&part->dupliweights);
|
||||
}
|
||||
}
|
||||
/************************************************/
|
||||
/* Freeing stuff */
|
||||
/************************************************/
|
||||
@ -307,6 +363,8 @@ void psys_free_settings(ParticleSettings *part)
|
||||
if(part->effector_weights)
|
||||
MEM_freeN(part->effector_weights);
|
||||
|
||||
BLI_freelistN(&part->dupliweights);
|
||||
|
||||
boid_free_settings(part->boids);
|
||||
}
|
||||
|
||||
@ -439,6 +497,9 @@ void psys_free_pdd(ParticleSystem *psys)
|
||||
if(psys->pdd->vedata)
|
||||
MEM_freeN(psys->pdd->vedata);
|
||||
psys->pdd->vedata = NULL;
|
||||
|
||||
psys->pdd->totpoint = 0;
|
||||
psys->pdd->tot_vec_size = 0;
|
||||
}
|
||||
}
|
||||
/* free everything */
|
||||
@ -2047,10 +2108,10 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float
|
||||
float roughfac;
|
||||
|
||||
roughfac=fac*(float)pow((double)t,shape);
|
||||
VECCOPY(rough,loc);
|
||||
Vec2Copyf(rough,loc);
|
||||
rough[0]=-1.0f+2.0f*rough[0];
|
||||
rough[1]=-1.0f+2.0f*rough[1];
|
||||
VecMulf(rough,roughfac);
|
||||
Vec2Mulf(rough,roughfac);
|
||||
|
||||
VECADDFAC(state->co,state->co,mat[0],rough[0]);
|
||||
VECADDFAC(state->co,state->co,mat[1],rough[1]);
|
||||
@ -3235,6 +3296,9 @@ static void default_particle_settings(ParticleSettings *part)
|
||||
part->size=0.05;
|
||||
part->childsize=1.0;
|
||||
|
||||
part->rotmode = PART_ROT_VEL;
|
||||
part->avemode = PART_AVE_SPIN;
|
||||
|
||||
part->child_nbr=10;
|
||||
part->ren_child_nbr=100;
|
||||
part->childrad=0.2f;
|
||||
@ -3788,6 +3852,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
|
||||
|
||||
/* get different child parameters from textures & vgroups */
|
||||
memset(&ctx, 0, sizeof(ParticleThreadContext));
|
||||
ctx.sim = *sim;
|
||||
ctx.dm = psmd->dm;
|
||||
ctx.ma = ma;
|
||||
/* TODO: assign vertex groups */
|
||||
@ -3856,6 +3921,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
|
||||
ChildParticle *cpa = NULL;
|
||||
float cfra;
|
||||
int totpart = psys->totpart;
|
||||
float timestep = psys_get_timestep(sim);
|
||||
|
||||
/* negative time means "use current time" */
|
||||
cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0);
|
||||
@ -3924,13 +3990,14 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
|
||||
calc_latt_deform(sim->psys->lattice, state->co,1.0f);
|
||||
}
|
||||
else{
|
||||
if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
|
||||
if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
|
||||
|| pa->prev_state.time <= 0.0f)
|
||||
copy_particle_key(state, &pa->state, 1);
|
||||
else if(pa->prev_state.time==state->time)
|
||||
copy_particle_key(state, &pa->prev_state, 1);
|
||||
else {
|
||||
/* let's interpolate to try to be as accurate as possible */
|
||||
if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) {
|
||||
if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) {
|
||||
ParticleKey keys[4];
|
||||
float dfra, keytime, frs_sec = sim->scene->r.frs_sec;
|
||||
|
||||
@ -3949,13 +4016,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
|
||||
keytime = (state->time - keys[1].time) / dfra;
|
||||
|
||||
/* convert velocity to timestep size */
|
||||
VecMulf(keys[1].vel, dfra / frs_sec);
|
||||
VecMulf(keys[2].vel, dfra / frs_sec);
|
||||
VecMulf(keys[1].vel, dfra * timestep);
|
||||
VecMulf(keys[2].vel, dfra * timestep);
|
||||
|
||||
psys_interpolate_particle(-1, keys, keytime, state, 1);
|
||||
|
||||
/* convert back to real velocity */
|
||||
VecMulf(state->vel, frs_sec / dfra);
|
||||
VecMulf(state->vel, 1.0f / (dfra * timestep));
|
||||
|
||||
VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime);
|
||||
QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime);
|
||||
|
@ -183,6 +183,8 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
|
||||
|
||||
if(totpart && totpart != psys->totpart) {
|
||||
newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
|
||||
if(psys->part->phystype == PART_PHYS_BOIDS)
|
||||
newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles");
|
||||
|
||||
if(psys->particles) {
|
||||
totsaved=MIN2(psys->totpart,totpart);
|
||||
@ -215,13 +217,12 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
|
||||
}
|
||||
|
||||
psys->particles=newpars;
|
||||
psys->totpart=totpart;
|
||||
|
||||
if(newboids) {
|
||||
LOOP_PARTICLES
|
||||
pa->boid = newboids++;
|
||||
}
|
||||
|
||||
psys->totpart=totpart;
|
||||
}
|
||||
|
||||
if(psys->child) {
|
||||
@ -1660,7 +1661,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
|
||||
ParticleKey state;
|
||||
//IpoCurve *icu=0; // XXX old animation system
|
||||
float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
|
||||
float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
|
||||
float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0};
|
||||
float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
|
||||
float q_phase[4], r_phase;
|
||||
int p = pa - psys->particles;
|
||||
@ -1773,7 +1774,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
|
||||
}
|
||||
}
|
||||
|
||||
if(part->phystype==PART_PHYS_BOIDS) {
|
||||
if(part->phystype==PART_PHYS_BOIDS && pa->boid) {
|
||||
BoidParticle *bpa = pa->boid;
|
||||
float dvec[3], q[4], mat[3][3];
|
||||
|
||||
@ -1839,6 +1840,23 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
|
||||
VECADDFAC(vel,vel,vtan,part->tanfac);
|
||||
//VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f));
|
||||
|
||||
/* *emitter object orientation */
|
||||
if(part->ob_vel[0]!=0.0) {
|
||||
VECCOPY(vec, ob->obmat[0]);
|
||||
Normalize(vec);
|
||||
VECADDFAC(vel, vel, vec, part->ob_vel[0]);
|
||||
}
|
||||
if(part->ob_vel[1]!=0.0) {
|
||||
VECCOPY(vec, ob->obmat[1]);
|
||||
Normalize(vec);
|
||||
VECADDFAC(vel, vel, vec, part->ob_vel[1]);
|
||||
}
|
||||
if(part->ob_vel[2]!=0.0) {
|
||||
VECCOPY(vec, ob->obmat[2]);
|
||||
Normalize(vec);
|
||||
VECADDFAC(vel, vel, vec, part->ob_vel[2]);
|
||||
}
|
||||
|
||||
/* *texture */
|
||||
/* TODO */
|
||||
|
||||
@ -3135,7 +3153,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
|
||||
ParticleSystem *psys = sim->psys;
|
||||
ParticleSettings *part=psys->part;
|
||||
KDTree *tree=0;
|
||||
//IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
|
||||
//IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
|
||||
/* Material *ma=give_current_material(sim->ob, part->omat); */
|
||||
BoidBrainData bbd;
|
||||
PARTICLE_P;
|
||||
|
@ -269,7 +269,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
|
||||
|
||||
/* determine rotation from velocity */
|
||||
if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
|
||||
vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot);
|
||||
vectoquat(pa->state.vel, OB_NEGX, OB_POSZ, pa->state.rot);
|
||||
}
|
||||
}
|
||||
static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data)
|
||||
@ -292,6 +292,23 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
|
||||
else
|
||||
BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2);
|
||||
|
||||
/* determine velocity from previous location */
|
||||
if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) {
|
||||
if(keys[1].time > keys[2].time) {
|
||||
VecSubf(keys[2].vel, keys[1].co, keys[2].co);
|
||||
VecMulf(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec);
|
||||
}
|
||||
else {
|
||||
VecSubf(keys[2].vel, keys[2].co, keys[1].co);
|
||||
VecMulf(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec);
|
||||
}
|
||||
}
|
||||
|
||||
/* determine rotation from velocity */
|
||||
if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) {
|
||||
vectoquat(keys[2].vel, OB_NEGX, OB_POSZ, keys[2].rot);
|
||||
}
|
||||
|
||||
if(cfra > pa->time)
|
||||
cfra1 = MAX2(cfra1, pa->time);
|
||||
|
||||
@ -301,7 +318,7 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f
|
||||
VecMulf(keys[2].vel, dfra / frs_sec);
|
||||
|
||||
psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
|
||||
QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra);
|
||||
QuatInterpol(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra);
|
||||
|
||||
VecMulf(pa->state.vel, frs_sec / dfra);
|
||||
|
||||
@ -594,7 +611,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
|
||||
if(psys->part->phystype == PART_PHYS_BOIDS)
|
||||
pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
|
||||
|
||||
if(psys->part->rotmode || psys->part->avemode)
|
||||
if(psys->part->rotmode!=PART_ROT_VEL
|
||||
|| psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f)
|
||||
pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
|
||||
|
||||
if(psys->part->flag & PART_ROT_DYN)
|
||||
|
@ -3033,6 +3033,7 @@ static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointC
|
||||
static void lib_link_particlesettings(FileData *fd, Main *main)
|
||||
{
|
||||
ParticleSettings *part;
|
||||
ParticleDupliWeight *dw;
|
||||
|
||||
part= main->particle.first;
|
||||
while(part) {
|
||||
@ -3048,6 +3049,10 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
|
||||
if(part->effector_weights)
|
||||
part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group);
|
||||
|
||||
dw = part->dupliweights.first;
|
||||
for(; dw; dw=dw->next)
|
||||
dw->ob = newlibadr(fd, part->id.lib, dw->ob);
|
||||
|
||||
if(part->boids) {
|
||||
BoidState *state = part->boids->states.first;
|
||||
BoidRule *rule;
|
||||
@ -3088,6 +3093,8 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
|
||||
else
|
||||
part->effector_weights = BKE_add_effector_weights(part->eff_group);
|
||||
|
||||
link_list(fd, &part->dupliweights);
|
||||
|
||||
part->boids= newdataadr(fd, part->boids);
|
||||
|
||||
if(part->boids) {
|
||||
|
@ -610,6 +610,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
|
||||
static void write_particlesettings(WriteData *wd, ListBase *idbase)
|
||||
{
|
||||
ParticleSettings *part;
|
||||
ParticleDupliWeight *dw;
|
||||
|
||||
part= idbase->first;
|
||||
while(part) {
|
||||
@ -622,6 +623,10 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
|
||||
writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
|
||||
writestruct(wd, DATA, "EffectorWeights", 1, part->effector_weights);
|
||||
|
||||
dw = part->dupliweights.first;
|
||||
for(; dw; dw=dw->next)
|
||||
writestruct(wd, DATA, "ParticleDupliWeight", 1, dw);
|
||||
|
||||
if(part->boids && part->phystype == PART_PHYS_BOIDS) {
|
||||
BoidState *state = part->boids->states.first;
|
||||
|
||||
|
@ -348,6 +348,82 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/************************ move up particle dupliweight operator *********************/
|
||||
|
||||
static int dupliob_move_up_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
|
||||
ParticleSystem *psys= ptr.data;
|
||||
ParticleSettings *part;
|
||||
ParticleDupliWeight *dw;
|
||||
|
||||
if(!psys)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
part = psys->part;
|
||||
for(dw=part->dupliweights.first; dw; dw=dw->next) {
|
||||
if(dw->flag & PART_DUPLIW_CURRENT && dw->prev) {
|
||||
BLI_remlink(&part->dupliweights, dw);
|
||||
BLI_insertlink(&part->dupliweights, dw->prev->prev, dw);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void PARTICLE_OT_dupliob_move_up(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Move Up Dupli Object";
|
||||
ot->idname= "PARTICLE_OT_dupliob_move_up";
|
||||
ot->description= "Move dupli object up in the list.";
|
||||
|
||||
ot->exec= dupliob_move_up_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/************************ move down particle dupliweight operator *********************/
|
||||
|
||||
static int dupliob_move_down_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
|
||||
ParticleSystem *psys= ptr.data;
|
||||
ParticleSettings *part;
|
||||
ParticleDupliWeight *dw;
|
||||
|
||||
if(!psys)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
part = psys->part;
|
||||
for(dw=part->dupliweights.first; dw; dw=dw->next) {
|
||||
if(dw->flag & PART_DUPLIW_CURRENT && dw->next) {
|
||||
BLI_remlink(&part->dupliweights, dw);
|
||||
BLI_insertlink(&part->dupliweights, dw->next, dw);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
|
||||
{
|
||||
ot->name= "Move Down Dupli Object";
|
||||
ot->idname= "PARTICLE_OT_dupliob_move_down";
|
||||
ot->description= "Move dupli object down in the list.";
|
||||
|
||||
ot->exec= dupliob_move_down_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/************************ connect/disconnect hair operators *********************/
|
||||
|
||||
static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
|
||||
|
@ -77,6 +77,9 @@ void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
|
||||
void PARTICLE_OT_connect_hair(struct wmOperatorType *ot);
|
||||
void PARTICLE_OT_disconnect_hair(struct wmOperatorType *ot);
|
||||
|
||||
void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot);
|
||||
void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot);
|
||||
|
||||
/* particle_boids.c */
|
||||
void BOID_OT_rule_add(struct wmOperatorType *ot);
|
||||
void BOID_OT_rule_del(struct wmOperatorType *ot);
|
||||
|
@ -78,6 +78,9 @@ static void operatortypes_particle(void)
|
||||
WM_operatortype_append(PARTICLE_OT_target_move_down);
|
||||
WM_operatortype_append(PARTICLE_OT_connect_hair);
|
||||
WM_operatortype_append(PARTICLE_OT_disconnect_hair);
|
||||
|
||||
WM_operatortype_append(PARTICLE_OT_dupliob_move_up);
|
||||
WM_operatortype_append(PARTICLE_OT_dupliob_move_down);
|
||||
}
|
||||
|
||||
static void keymap_particle(wmWindowManager *wm)
|
||||
|
@ -3358,7 +3358,30 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
|
||||
}
|
||||
|
||||
/* *********** drawing for particles ************* */
|
||||
static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
|
||||
{
|
||||
/* draw created data arrays */
|
||||
switch(draw_as){
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
glDrawArrays(GL_LINES, 0, 6*totpoint);
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
glDrawArrays(GL_LINES, 0, 2*totpoint);
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(ob_dt<=OB_WIRE || select)
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
else
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4*totpoint);
|
||||
break;
|
||||
default:
|
||||
glDrawArrays(GL_POINTS, 0, totpoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
|
||||
{
|
||||
float vec[3], vec2[3];
|
||||
@ -3401,7 +3424,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
|
||||
cd[7]=cd[10]=1.0;
|
||||
cd[13]=cd[12]=cd[15]=cd[16]=0.0;
|
||||
cd[14]=cd[17]=1.0;
|
||||
cd+=18;
|
||||
pdd->cd+=18;
|
||||
|
||||
VECCOPY(vec2,state->co);
|
||||
}
|
||||
@ -3552,7 +3575,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
if(psys_in_edit_mode(scene, psys) && (pset->flag & PE_DRAW_PART)==0)
|
||||
return;
|
||||
|
||||
if(part->draw_as==PART_DRAW_NOT) return;
|
||||
if(part->draw_as == PART_DRAW_REND)
|
||||
draw_as = part->ren_as;
|
||||
else
|
||||
draw_as = part->draw_as;
|
||||
|
||||
if(draw_as == PART_DRAW_NOT)
|
||||
return;
|
||||
|
||||
/* 2. */
|
||||
sim.psmd = psmd = psys_get_modifier(ob,psys);
|
||||
@ -3582,26 +3611,22 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
|
||||
if(v3d->zbuf) glDepthMask(1);
|
||||
|
||||
if(select)
|
||||
cpack(0xFFFFFF);
|
||||
else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
|
||||
if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
|
||||
glColor3f(ma->r,ma->g,ma->b);
|
||||
|
||||
ma_r = ma->r;
|
||||
ma_g = ma->g;
|
||||
ma_b = ma->b;
|
||||
|
||||
if(pdd) {
|
||||
pdd->ma_r = &ma_r;
|
||||
pdd->ma_g = &ma_g;
|
||||
pdd->ma_b = &ma_b;
|
||||
}
|
||||
|
||||
create_cdata = 1;
|
||||
}
|
||||
else
|
||||
cpack(0);
|
||||
|
||||
if(pdd) {
|
||||
pdd->ma_r = &ma_r;
|
||||
pdd->ma_g = &ma_g;
|
||||
pdd->ma_b = &ma_b;
|
||||
}
|
||||
|
||||
timestep= psys_get_timestep(&sim);
|
||||
|
||||
if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
|
||||
@ -3612,11 +3637,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
|
||||
totpart=psys->totpart;
|
||||
|
||||
if(part->draw_as==PART_DRAW_REND)
|
||||
draw_as = part->ren_as;
|
||||
else
|
||||
draw_as = part->draw_as;
|
||||
|
||||
//if(part->flag&PART_GLOB_TIME)
|
||||
cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
|
||||
|
||||
@ -3646,6 +3666,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
pixsize*=2.0;
|
||||
else
|
||||
pixsize*=part->draw_size;
|
||||
|
||||
if(draw_as==PART_DRAW_AXIS)
|
||||
create_cdata = 1;
|
||||
break;
|
||||
case PART_DRAW_OB:
|
||||
if(part->dup_ob==0)
|
||||
@ -3693,9 +3716,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
Normalize(imat[1]);
|
||||
}
|
||||
|
||||
if(!create_cdata && pdd && pdd->cdata) {
|
||||
MEM_freeN(pdd->cdata);
|
||||
pdd->cdata = pdd->cd = NULL;
|
||||
}
|
||||
|
||||
/* 4. */
|
||||
if(draw_as && draw_as!=PART_DRAW_PATH) {
|
||||
if(draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC)==0) {
|
||||
int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
|
||||
int create_ndata = 0;
|
||||
|
||||
if(!pdd)
|
||||
pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData");
|
||||
@ -3705,37 +3734,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
psys_make_temp_pointcache(ob, psys);
|
||||
}
|
||||
|
||||
switch(draw_as) {
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
tot_vec_size *= 6;
|
||||
if(draw_as != PART_DRAW_CROSS)
|
||||
create_cdata = 1;
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
tot_vec_size *= 2;
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
tot_vec_size *= 4;
|
||||
create_ndata = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(pdd->tot_vec_size != tot_vec_size)
|
||||
psys_free_pdd(psys);
|
||||
|
||||
if(draw_as!=PART_DRAW_CIRC) {
|
||||
switch(draw_as) {
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
if(draw_as != PART_DRAW_CROSS || create_cdata)
|
||||
if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
|
||||
if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
if(create_cdata)
|
||||
if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
|
||||
if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(create_cdata)
|
||||
if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
|
||||
if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
|
||||
if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
|
||||
break;
|
||||
default:
|
||||
if(create_cdata)
|
||||
if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata");
|
||||
if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata");
|
||||
}
|
||||
}
|
||||
if(!pdd->vdata)
|
||||
pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
|
||||
if(create_cdata && !pdd->cdata)
|
||||
pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
|
||||
if(create_ndata && !pdd->ndata)
|
||||
pdd->ndata = MEM_callocN(tot_vec_size, "particle_vdata");
|
||||
|
||||
if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
|
||||
if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
|
||||
if(!pdd->vedata)
|
||||
pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
|
||||
|
||||
need_v = 1;
|
||||
}
|
||||
|
||||
@ -3744,11 +3772,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
pdd->cd= pdd->cdata;
|
||||
pdd->nd= pdd->ndata;
|
||||
pdd->tot_vec_size= tot_vec_size;
|
||||
|
||||
psys->lattice= psys_get_lattice(&sim);
|
||||
}
|
||||
|
||||
if(draw_as){
|
||||
psys->lattice= psys_get_lattice(&sim);
|
||||
|
||||
if(draw_as!=PART_DRAW_PATH){
|
||||
/* 5. */
|
||||
if((pdd->flag & PARTICLE_DRAW_DATA_UPDATED)
|
||||
&& (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) {
|
||||
@ -3836,156 +3864,139 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
r_length = PSYS_FRAND(a + 22);
|
||||
}
|
||||
|
||||
if(draw_as!=PART_DRAW_PATH){
|
||||
drawn = 0;
|
||||
if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
|
||||
float length = part->path_end * (1.0 - part->randlength * r_length);
|
||||
int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
|
||||
float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
|
||||
float dt = length / (trail_count ? (float)trail_count : 1.0f);
|
||||
int i=0;
|
||||
drawn = 0;
|
||||
if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
|
||||
float length = part->path_end * (1.0 - part->randlength * r_length);
|
||||
int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
|
||||
float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
|
||||
float dt = length / (trail_count ? (float)trail_count : 1.0f);
|
||||
int i=0;
|
||||
|
||||
ct+=dt;
|
||||
for(i=0; i < trail_count; i++, ct += dt) {
|
||||
if(part->draw & PART_ABS_PATH_TIME) {
|
||||
if(ct < pa_birthtime || ct > pa_dietime)
|
||||
continue;
|
||||
}
|
||||
else if(ct < 0.0f || ct > 1.0f)
|
||||
ct+=dt;
|
||||
for(i=0; i < trail_count; i++, ct += dt) {
|
||||
if(part->draw & PART_ABS_PATH_TIME) {
|
||||
if(ct < pa_birthtime || ct > pa_dietime)
|
||||
continue;
|
||||
|
||||
state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
|
||||
psys_get_particle_on_path(&sim,a,&state,need_v);
|
||||
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
|
||||
/* create actiual particle data */
|
||||
if(draw_as == PART_DRAW_BB) {
|
||||
bb.size = pa_size;
|
||||
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
|
||||
bb.time = ct;
|
||||
}
|
||||
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
|
||||
|
||||
totpoint++;
|
||||
drawn = 1;
|
||||
}
|
||||
else if(ct < 0.0f || ct > 1.0f)
|
||||
continue;
|
||||
|
||||
state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
|
||||
psys_get_particle_on_path(&sim,a,&state,need_v);
|
||||
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
|
||||
/* create actiual particle data */
|
||||
if(draw_as == PART_DRAW_BB) {
|
||||
bb.size = pa_size;
|
||||
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
|
||||
bb.time = ct;
|
||||
}
|
||||
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd);
|
||||
|
||||
totpoint++;
|
||||
drawn = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.time=cfra;
|
||||
if(psys_get_particle_state(&sim,a,&state,0)){
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.time=cfra;
|
||||
if(psys_get_particle_state(&sim,a,&state,0)){
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
|
||||
/* create actiual particle data */
|
||||
if(draw_as == PART_DRAW_BB) {
|
||||
bb.size = pa_size;
|
||||
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
|
||||
bb.time = pa_time;
|
||||
}
|
||||
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
|
||||
|
||||
totpoint++;
|
||||
drawn = 1;
|
||||
/* create actiual particle data */
|
||||
if(draw_as == PART_DRAW_BB) {
|
||||
bb.size = pa_size;
|
||||
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
|
||||
bb.time = pa_time;
|
||||
}
|
||||
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd);
|
||||
|
||||
totpoint++;
|
||||
drawn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(drawn) {
|
||||
/* additional things to draw for each particle */
|
||||
/* (velocity, size and number) */
|
||||
if(pdd->vedata){
|
||||
VECCOPY(pdd->ved,state.co);
|
||||
pdd->ved+=3;
|
||||
VECCOPY(vel,state.vel);
|
||||
VecMulf(vel,timestep);
|
||||
VECADD(pdd->ved,state.co,vel);
|
||||
pdd->ved+=3;
|
||||
|
||||
totve++;
|
||||
}
|
||||
|
||||
if(drawn) {
|
||||
/* additional things to draw for each particle */
|
||||
/* (velocity, size and number) */
|
||||
if(pdd->vedata){
|
||||
VECCOPY(pdd->ved,state.co);
|
||||
pdd->ved+=3;
|
||||
VECCOPY(vel,state.vel);
|
||||
VecMulf(vel,timestep);
|
||||
VECADD(pdd->ved,state.co,vel);
|
||||
pdd->ved+=3;
|
||||
if(part->draw & PART_DRAW_SIZE){
|
||||
setlinestyle(3);
|
||||
drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
|
||||
setlinestyle(0);
|
||||
}
|
||||
|
||||
totve++;
|
||||
}
|
||||
if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
|
||||
val[0]= '\0';
|
||||
|
||||
if(part->draw&PART_DRAW_NUM)
|
||||
sprintf(val, " %i", a);
|
||||
|
||||
if(part->draw & PART_DRAW_SIZE){
|
||||
setlinestyle(3);
|
||||
drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
|
||||
setlinestyle(0);
|
||||
}
|
||||
if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
|
||||
sprintf(val, "%s:", val);
|
||||
|
||||
if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
|
||||
val[0]= '\0';
|
||||
|
||||
if(part->draw&PART_DRAW_NUM)
|
||||
sprintf(val, " %i", a);
|
||||
if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
|
||||
sprintf(val, "%s %.2f", val, pa_health);
|
||||
|
||||
if(part->draw&PART_DRAW_NUM && part->draw&PART_DRAW_HEALTH)
|
||||
sprintf(val, "%s:", val);
|
||||
|
||||
if(part->draw&PART_DRAW_HEALTH && a < totpart && part->phystype==PART_PHYS_BOIDS)
|
||||
sprintf(val, "%s %.2f", val, pa_health);
|
||||
|
||||
/* in path drawing state.co is the end point */
|
||||
view3d_cached_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0);
|
||||
}
|
||||
/* in path drawing state.co is the end point */
|
||||
view3d_cached_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 6. */
|
||||
|
||||
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(draw_as==PART_DRAW_PATH){
|
||||
ParticleCacheKey **cache, *path;
|
||||
float *cd2=0,*cdata2=0;
|
||||
if(draw_as==PART_DRAW_PATH){
|
||||
ParticleCacheKey **cache, *path;
|
||||
float *cd2=0,*cdata2=0;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
/* setup gl flags */
|
||||
if(ob_dt > OB_WIRE) {
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
/* setup gl flags */
|
||||
if(ob_dt > OB_WIRE) {
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
else {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glEnable(GL_LIGHTING);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
else {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_LIGHTING);
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glDisable(GL_LIGHTING);
|
||||
UI_ThemeColor(TH_WIRE);
|
||||
}
|
||||
|
||||
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
|
||||
totpart=0;
|
||||
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
|
||||
totpart=0;
|
||||
|
||||
/* draw actual/parent particles */
|
||||
cache=psys->pathcache;
|
||||
for(a=0, pa=psys->particles; a<totpart; a++, pa++){
|
||||
path=cache[a];
|
||||
if(path->steps > 0) {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||
|
||||
if(ob_dt > OB_WIRE) {
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw child particles */
|
||||
cache=psys->childcache;
|
||||
for(a=0; a<totchild; a++){
|
||||
path=cache[a];
|
||||
/* draw actual/parent particles */
|
||||
cache=psys->pathcache;
|
||||
for(a=0, pa=psys->particles; a<totpart; a++, pa++){
|
||||
path=cache[a];
|
||||
if(path->steps > 0) {
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||
|
||||
if(ob_dt > OB_WIRE) {
|
||||
@ -3996,85 +4007,103 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
|
||||
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw child particles */
|
||||
cache=psys->childcache;
|
||||
for(a=0; a<totchild; a++){
|
||||
path=cache[a];
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
|
||||
|
||||
|
||||
/* restore & clean up */
|
||||
if(ob_dt > OB_WIRE) {
|
||||
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glDisable(GL_COLOR_ARRAY);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
|
||||
}
|
||||
|
||||
if(cdata2)
|
||||
MEM_freeN(cdata2);
|
||||
cd2=cdata2=0;
|
||||
|
||||
glLineWidth(1.0f);
|
||||
}
|
||||
else if(draw_as!=PART_DRAW_CIRC){
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
/* setup created data arrays */
|
||||
if(pdd->vdata){
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
|
||||
}
|
||||
else
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
/* billboards are drawn this way */
|
||||
if(pdd->ndata && ob_dt>OB_WIRE){
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, pdd->ndata);
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
else{
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
if(pdd->cdata){
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
|
||||
}
|
||||
|
||||
/* draw created data arrays */
|
||||
switch(draw_as){
|
||||
case PART_DRAW_AXIS:
|
||||
case PART_DRAW_CROSS:
|
||||
glDrawArrays(GL_LINES, 0, 6*totpoint);
|
||||
break;
|
||||
case PART_DRAW_LINE:
|
||||
glDrawArrays(GL_LINES, 0, 2*totpoint);
|
||||
break;
|
||||
case PART_DRAW_BB:
|
||||
if(ob_dt<=OB_WIRE)
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
|
||||
glDrawArrays(GL_QUADS, 0, 4*totpoint);
|
||||
break;
|
||||
default:
|
||||
glDrawArrays(GL_POINTS, 0, totpoint);
|
||||
break;
|
||||
}
|
||||
|
||||
pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
|
||||
pdd->totpoint = totpoint;
|
||||
glDrawArrays(GL_LINE_STRIP, 0, path->steps + 1);
|
||||
}
|
||||
|
||||
if(pdd->vedata){
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
cpack(0xC0C0C0);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
|
||||
|
||||
glDrawArrays(GL_LINES, 0, 2*totve);
|
||||
|
||||
/* restore & clean up */
|
||||
if(ob_dt > OB_WIRE) {
|
||||
if(part->draw&PART_DRAW_MAT_COL)
|
||||
glDisable(GL_COLOR_ARRAY);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT, polygonmode[0]);
|
||||
glPolygonMode(GL_BACK, polygonmode[1]);
|
||||
if(cdata2)
|
||||
MEM_freeN(cdata2);
|
||||
cd2=cdata2=0;
|
||||
|
||||
glLineWidth(1.0f);
|
||||
}
|
||||
else if(ELEM(draw_as, 0, PART_DRAW_CIRC)==0){
|
||||
int point_size = 1;
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
/* enable point data array */
|
||||
if(pdd->vdata){
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
|
||||
}
|
||||
else
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if(select) {
|
||||
UI_ThemeColor(TH_ACTIVE);
|
||||
|
||||
if(part->draw_size)
|
||||
glPointSize(part->draw_size + 2);
|
||||
else
|
||||
glPointSize(4.0);
|
||||
|
||||
glLineWidth(3.0);
|
||||
|
||||
draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
|
||||
}
|
||||
|
||||
/* restore from select */
|
||||
glColor3f(ma_r,ma_g,ma_b);
|
||||
glPointSize(part->draw_size ? part->draw_size : 2.0);
|
||||
glLineWidth(1.0);
|
||||
|
||||
/* enable other data arrays */
|
||||
|
||||
/* billboards are drawn this way */
|
||||
if(pdd->ndata && ob_dt>OB_WIRE){
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, pdd->ndata);
|
||||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
else{
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
if(pdd->cdata){
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
|
||||
}
|
||||
|
||||
draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
|
||||
|
||||
pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
|
||||
pdd->totpoint = totpoint;
|
||||
}
|
||||
|
||||
if(pdd && pdd->vedata){
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
cpack(0xC0C0C0);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
|
||||
|
||||
glDrawArrays(GL_LINES, 0, 2*totve);
|
||||
}
|
||||
|
||||
glPolygonMode(GL_FRONT, polygonmode[0]);
|
||||
glPolygonMode(GL_BACK, polygonmode[1]);
|
||||
|
||||
/* 7. */
|
||||
|
||||
@ -4087,6 +4116,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
|
||||
|
||||
psys->flag &= ~PSYS_DRAWING;
|
||||
|
||||
/* draw data can't be saved for billboards as they must update to target changes */
|
||||
if(draw_as == PART_DRAW_BB) {
|
||||
psys_free_pdd(psys);
|
||||
pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED;
|
||||
}
|
||||
|
||||
if(psys->lattice){
|
||||
end_latt_deform(psys->lattice);
|
||||
psys->lattice= NULL;
|
||||
|
@ -56,14 +56,14 @@ typedef enum PFieldType {
|
||||
} PFieldType;
|
||||
|
||||
typedef struct PartDeflect {
|
||||
int flag; /* general settings flag */
|
||||
short deflect; /* Deflection flag - does mesh deflect particles */
|
||||
short forcefield; /* Force field type, do the vertices attract / repel particles? */
|
||||
short flag; /* general settings flag */
|
||||
short falloff; /* fall-off type */
|
||||
short shape; /* point, plane or surface */
|
||||
short tex_mode; /* texture effector */
|
||||
short kink, kink_axis; /* for curve guide */
|
||||
short zdir, rt;
|
||||
short zdir;
|
||||
|
||||
/* Main effector values */
|
||||
float f_strength; /* The strength of the force (+ or - ) */
|
||||
|
@ -78,6 +78,13 @@ typedef struct ParticleTarget {
|
||||
float time, duration;
|
||||
} ParticleTarget;
|
||||
|
||||
typedef struct ParticleDupliWeight {
|
||||
struct ParticleDupliWeight *next, *prev;
|
||||
struct Object *ob;
|
||||
short count;
|
||||
short flag, rt[2];
|
||||
} ParticleDupliWeight;
|
||||
|
||||
typedef struct ParticleData {
|
||||
ParticleKey state; /* current global coordinates */
|
||||
|
||||
@ -148,6 +155,7 @@ typedef struct ParticleSettings {
|
||||
|
||||
/* initial velocity factors */
|
||||
float normfac, obfac, randfac, partfac, tanfac, tanphase, reactfac;
|
||||
float ob_vel[3], rt;
|
||||
float avefac, phasefac, randrotfac, randphasefac;
|
||||
/* physical properties */
|
||||
float mass, size, randsize, reactshape;
|
||||
@ -179,6 +187,7 @@ typedef struct ParticleSettings {
|
||||
int keyed_loops;
|
||||
|
||||
struct Group *dup_group;
|
||||
struct ListBase dupliweights;
|
||||
struct Group *eff_group; // deprecated
|
||||
struct Object *dup_ob;
|
||||
struct Object *bb_ob;
|
||||
@ -324,12 +333,12 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
|
||||
|
||||
/* part->draw */
|
||||
#define PART_DRAW_VEL 1
|
||||
//#define PART_DRAW_PATH_LEN 2
|
||||
#define PART_DRAW_GLOBAL_OB 2
|
||||
#define PART_DRAW_SIZE 4
|
||||
#define PART_DRAW_EMITTER 8 /* render emitter also */
|
||||
#define PART_DRAW_HEALTH 16
|
||||
#define PART_ABS_PATH_TIME 32
|
||||
//#define PART_DRAW_TRAIL 64 /* deprecated */
|
||||
#define PART_DRAW_COUNT_GR 64
|
||||
#define PART_DRAW_BB_LOCK 128
|
||||
#define PART_DRAW_PARENT 256
|
||||
#define PART_DRAW_NUM 512
|
||||
@ -444,6 +453,9 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
|
||||
#define PARS_ALIVE 3
|
||||
#define PARS_DYING 4
|
||||
|
||||
/* ParticleDupliWeight->flag */
|
||||
#define PART_DUPLIW_CURRENT 1
|
||||
|
||||
/* psys->vg */
|
||||
#define PSYS_TOT_VG 12
|
||||
|
||||
|
@ -45,6 +45,13 @@ EnumPropertyItem effector_shape_items[] = {
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem curve_shape_items[] = {
|
||||
{PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
|
||||
{PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
|
||||
{PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem empty_shape_items[] = {
|
||||
{PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
|
||||
{PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
|
||||
@ -59,6 +66,13 @@ EnumPropertyItem vortex_shape_items[] = {
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem curve_vortex_shape_items[] = {
|
||||
{PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
|
||||
{PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
|
||||
{PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve (New)", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
EnumPropertyItem empty_vortex_shape_items[] = {
|
||||
{PFIELD_SHAPE_POINT, "POINT", 0, "Old", ""},
|
||||
{PFIELD_SHAPE_PLANE, "PLANE", 0, "New", ""},
|
||||
@ -538,9 +552,11 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr,
|
||||
|
||||
/* needed for doc generation */
|
||||
RNA_enum_items_add(&item, &totitem, effector_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, curve_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, empty_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, vortex_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, empty_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, curve_vortex_shape_items);
|
||||
RNA_enum_items_add(&item, &totitem, empty_vortex_shape_items);
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
|
||||
*free= 1;
|
||||
@ -553,7 +569,13 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *C, PointerRNA *ptr,
|
||||
|
||||
ob= (Object*)ptr->id.data;
|
||||
|
||||
if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
|
||||
if(ob->type == OB_CURVE) {
|
||||
if(ob->pd->forcefield == PFIELD_VORTEX)
|
||||
return curve_vortex_shape_items;
|
||||
|
||||
return curve_shape_items;
|
||||
}
|
||||
else if(ELEM3(ob->type, OB_MESH, OB_SURF, OB_FONT)) {
|
||||
if(ob->pd->forcefield == PFIELD_VORTEX)
|
||||
return vortex_shape_items;
|
||||
|
||||
@ -783,11 +805,11 @@ static void rna_def_effector_weight(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "All", "All effector's weight.");
|
||||
RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
|
||||
|
||||
prop= RNA_def_property(srna, "spherical", PROP_FLOAT, PROP_NONE);
|
||||
prop= RNA_def_property(srna, "force", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "weight[1]");
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight.");
|
||||
RNA_def_property_ui_text(prop, "Force", "Force effector weight.");
|
||||
RNA_def_property_update(prop, 0, "rna_EffectorWeight_update");
|
||||
|
||||
prop= RNA_def_property(srna, "vortex", PROP_FLOAT, PROP_NONE);
|
||||
@ -1113,6 +1135,11 @@ static void rna_def_field(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_DO_ROTATION);
|
||||
RNA_def_property_ui_text(prop, "Rotation", "Effect particles' dynamic rotation");
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
prop= RNA_def_property(srna, "do_absorption", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY);
|
||||
RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects");
|
||||
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
|
||||
|
||||
/* Pointer */
|
||||
|
||||
|
@ -105,6 +105,7 @@ EnumPropertyItem part_hair_ren_as_items[] = {
|
||||
#include "BKE_pointcache.h"
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
/* property update functions */
|
||||
static void particle_recalc(bContext *C, PointerRNA *ptr, short flag)
|
||||
@ -433,6 +434,71 @@ static int rna_ParticleSystem_edited_get(PointerRNA *ptr)
|
||||
else
|
||||
return (psys->pointcache->edit && psys->pointcache->edit->edited);
|
||||
}
|
||||
static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
|
||||
{
|
||||
ParticleSettings *part= (ParticleSettings*)ptr->id.data;
|
||||
ParticleDupliWeight *dw = part->dupliweights.first;
|
||||
|
||||
for(; dw; dw=dw->next) {
|
||||
if(dw->flag & PART_DUPLIW_CURRENT)
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_ParticleDupliWeight, dw);
|
||||
}
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
|
||||
}
|
||||
static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min, int *max)
|
||||
{
|
||||
ParticleSettings *part= (ParticleSettings*)ptr->id.data;
|
||||
*min= 0;
|
||||
*max= BLI_countlist(&part->dupliweights)-1;
|
||||
*max= MAX2(0, *max);
|
||||
}
|
||||
|
||||
static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
|
||||
{
|
||||
ParticleSettings *part= (ParticleSettings*)ptr->id.data;
|
||||
ParticleDupliWeight *dw = part->dupliweights.first;
|
||||
int i=0;
|
||||
|
||||
for(; dw; dw=dw->next, i++)
|
||||
if(dw->flag & PART_DUPLIW_CURRENT)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value)
|
||||
{
|
||||
ParticleSettings *part= (ParticleSettings*)ptr->id.data;
|
||||
ParticleDupliWeight *dw = part->dupliweights.first;
|
||||
int i=0;
|
||||
|
||||
for(; dw; dw=dw->next, i++) {
|
||||
if(i==value)
|
||||
dw->flag |= PART_DUPLIW_CURRENT;
|
||||
else
|
||||
dw->flag &= ~PART_DUPLIW_CURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
static int rna_ParticleDupliWeight_name_length(PointerRNA *ptr)
|
||||
{
|
||||
ParticleDupliWeight *dw= ptr->data;
|
||||
|
||||
if(dw->ob)
|
||||
return strlen(dw->ob->id.name+2) + 7;
|
||||
else
|
||||
return 9 + 7;
|
||||
}
|
||||
|
||||
static void rna_ParticleDupliWeight_name_get(PointerRNA *ptr, char *str)
|
||||
{
|
||||
ParticleDupliWeight *dw= ptr->data;
|
||||
|
||||
if(dw->ob)
|
||||
sprintf(str, "%s: %i", dw->ob->id.name+2, dw->count);
|
||||
else
|
||||
strcpy(str, "No object");
|
||||
}
|
||||
EnumPropertyItem from_items[] = {
|
||||
{PART_FROM_VERT, "VERT", 0, "Vertexes", ""},
|
||||
{PART_FROM_FACE, "FACE", 0, "Faces", ""},
|
||||
@ -726,6 +792,27 @@ static void rna_def_particle(BlenderRNA *brna)
|
||||
// short rt2;
|
||||
}
|
||||
|
||||
static void rna_def_particle_dupliweight(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "ParticleDupliWeight", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Particle Dupliobject Weight", "Weight of a particle dupliobject in a group.");
|
||||
RNA_def_struct_sdna(srna, "ParticleDupliWeight");
|
||||
|
||||
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_funcs(prop, "rna_ParticleDupliWeight_name_get", "rna_ParticleDupliWeight_name_length", NULL);
|
||||
RNA_def_property_ui_text(prop, "Name", "Particle dupliobject name.");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_struct_name_property(srna, prop);
|
||||
|
||||
prop= RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_range(prop, 0, INT_MAX);
|
||||
RNA_def_property_ui_text(prop, "Count", "The number of times this object is repeated with respect to other objects.");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
||||
}
|
||||
|
||||
static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@ -1069,6 +1156,16 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Pick Random", "Pick objects from group randomly");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
||||
|
||||
prop= RNA_def_property(srna, "use_group_count", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_COUNT_GR);
|
||||
RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same group");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
||||
|
||||
prop= RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB);
|
||||
RNA_def_property_ui_text(prop, "Use Global", "Use object's global coordinates for duplication.");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
||||
|
||||
prop= RNA_def_property(srna, "render_adaptive", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
|
||||
RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path");
|
||||
@ -1374,6 +1471,13 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Reactor", "Let the vector away from the target particles location give the particle a starting speed.");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "object_aligned_factor", PROP_FLOAT, PROP_VELOCITY);
|
||||
RNA_def_property_float_sdna(prop, NULL, "ob_vel");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
RNA_def_property_ui_text(prop, "Object Aligned", "Let the emitter object orientation give the particle a starting speed");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "angular_velocity_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "avefac");
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
@ -1426,19 +1530,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
|
||||
|
||||
/* global physical properties */
|
||||
prop= RNA_def_property(srna, "acceleration", PROP_FLOAT, PROP_ACCELERATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "acc");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
RNA_def_property_ui_text(prop, "Acceleration", "Constant acceleration");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION);
|
||||
RNA_def_property_float_sdna(prop, NULL, "acc[2]");
|
||||
RNA_def_property_range(prop, -200.0f, 200.0f);
|
||||
RNA_def_property_ui_text(prop, "Gravity", "Constant acceleration in global Z axis direction");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_reset");
|
||||
|
||||
prop= RNA_def_property(srna, "drag_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "dragfac");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
@ -1665,6 +1756,19 @@ static void rna_def_particle_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Dupli Group", "Show Objects in this Group in place of particles");
|
||||
RNA_def_property_update(prop, 0, "rna_Particle_redo");
|
||||
|
||||
prop= RNA_def_property(srna, "dupliweights", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ParticleDupliWeight");
|
||||
RNA_def_property_ui_text(prop, "Dupli Group Weights", "Weights for all of the objects in the dupli group.");
|
||||
|
||||
prop= RNA_def_property(srna, "active_dupliweight", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ParticleDupliWeight");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_ParticleDupliWeight_active_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Active Dupli Object", "");
|
||||
|
||||
prop= RNA_def_property(srna, "active_dupliweight_index", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_funcs(prop, "rna_ParticleDupliWeight_active_index_get", "rna_ParticleDupliWeight_active_index_set", "rna_ParticleDupliWeight_active_index_range");
|
||||
RNA_def_property_ui_text(prop, "Active Dupli Object Index", "");
|
||||
|
||||
prop= RNA_def_property(srna, "dupli_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "dup_ob");
|
||||
RNA_def_property_struct_type(prop, "Object");
|
||||
@ -2024,6 +2128,7 @@ void RNA_def_particle(BlenderRNA *brna)
|
||||
|
||||
rna_def_child_particle(brna);
|
||||
rna_def_particle(brna);
|
||||
rna_def_particle_dupliweight(brna);
|
||||
rna_def_particle_system(brna);
|
||||
rna_def_particle_settings(brna);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user