Initial code for boids v2

Too many new features to list! But here are the biggies:
- Boids can move on air and/or land, or climb a goal object.
- Proper interaction with collision objects.
	* Closest collision object in negative z direction is considered as ground.
	* Other collision objects are obstacles and boids collide with them.
- Boid behavior rules are now added to a dynamic list.
	* Many new rules and many still not implemented.
	* Different rule evaluation modes (fuzzy, random, average).
- Only particle systems defined by per system "boid relations" are considered for simulation of that system.
	* This is in addition to the boids own system of course.
	* Relations define other systems as "neutral", "friend" or "enemy".
- All effectors now effect boid physics, not boid brains.
	* This allows forcing boids somewhere.
	* Exception to this is new "boid" effector, which defines boid predators (positive strength) and goals (negative strength).
	
Known issue:
- Boid health isn't yet stored in pointcache so simulations with "fight" rule are not be read from cache properly.
- Object/Group visualization object's animation is not played in "particle time". This is definately the wanted behavior, but isn't possible with the current state of dupliobject code.

Other new features:
- Particle systems can now be named separately from particle settings.
	* Default name for particle settings is now "ParticleSettings" instead of "PSys"
- Per particle system list of particle effector weights.
	* Enables different effection strengths for particles from different particle systems with without messing around with effector group setting.

Other code changes:
- KDTree now supports range search as it's needed for new boids.
- "Keyed particle targets" renamed as general "particle targets", as they're needed for boids too. (this might break some files saved with new keyed particles)

Bug fixes:
- Object & group visualizations didn't work.
- Interpolating pointcache didn't do rotation.
This commit is contained in:
2009-07-20 23:52:53 +00:00
parent 01b787636b
commit b4353a8443
34 changed files with 4074 additions and 1193 deletions

View File

@@ -40,27 +40,33 @@ class PARTICLE_PT_particles(ParticleButtonsPanel):
col.itemO("object.particle_system_remove", icon="ICON_ZOOMOUT", text="")
if psys:
split = layout.split(percentage=0.65)
part = psys.settings
split.template_ID(psys, "settings", new="particle.new")
split = layout.split(percentage=0.32)
col = split.column()
col.itemL(text="Name:")
if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
col.itemL(text="Settings:")
col.itemL(text="Type:")
col = split.column()
col.itemR(psys, "name", text="")
if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
col.template_ID(psys, "settings", new="particle.new")
#row = layout.row()
#row.itemL(text="Viewport")
#row.itemL(text="Render")
part = psys.settings
if part:
ptype = psys.settings.type
if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
if part.type not in ('EMITTER', 'REACTOR', 'HAIR'):
layout.itemL(text="No settings for fluid particles")
return
split = layout.split(percentage=0.65)
split.enabled = particle_panel_enabled(psys)
split.itemR(part, "type")
split.itemR(psys, "seed")
row=col.row()
row.enabled = particle_panel_enabled(psys)
row.itemR(part, "type", text="")
row.itemR(psys, "seed")
split = layout.split(percentage=0.65)
if part.type=='HAIR':
@@ -183,6 +189,13 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
class PARTICLE_PT_initial(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_initial"
__label__ = "Velocity"
def poll(self, context):
if particle_panel_poll(context):
psys = context.particle_system
return psys.settings.physics_type != 'BOIDS'
else:
return False
def draw(self, context):
layout = self.layout
@@ -250,13 +263,11 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
psys = context.particle_system
part = psys.settings
layout.enabled = layout.enabled = particle_panel_enabled(psys)
layout.enabled = particle_panel_enabled(psys)
row = layout.row()
row.itemR(part, "physics_type", expand=True)
if part.physics_type != 'NO':
layout.itemR(part, "effector_group")
row = layout.row()
col = row.column(align=True)
col.itemR(part, "particle_size")
@@ -264,12 +275,10 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
col = row.column(align=True)
col.itemR(part, "mass")
col.itemR(part, "sizemass", text="Multiply mass with size")
split = layout.split()
sub = split.column()
if part.physics_type == 'NEWTON':
split = layout.split()
sub = split.column()
sub.itemL(text="Forces:")
sub.itemR(part, "brownian_factor")
@@ -280,6 +289,9 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
sub.itemR(part, "acceleration")
elif part.physics_type == 'KEYED':
split = layout.split()
sub = split.column()
row = layout.row()
col = row.column()
col.active = not psys.keyed_timing
@@ -287,38 +299,189 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
row.itemR(psys, "keyed_timing", text="Use Timing")
layout.itemL(text="Keys:")
elif part.physics_type=='BOIDS':
boids = part.boids
row = layout.row()
row.itemR(boids, "allow_flight")
row.itemR(boids, "allow_land")
row.itemR(boids, "allow_climb")
split = layout.split()
sub = split.column()
col = sub.column(align=True)
col.active = boids.allow_flight
col.itemR(boids, "air_max_speed")
col.itemR(boids, "air_min_speed", slider="True")
col.itemR(boids, "air_max_acc", slider="True")
col.itemR(boids, "air_max_ave", slider="True")
col.itemR(boids, "air_personal_space")
row = col.row()
row.active = (boids.allow_land or boids.allow_climb) and boids.allow_flight
row.itemR(boids, "landing_smoothness")
sub = split.column()
col = sub.column(align=True)
col.active = boids.allow_land or boids.allow_climb
col.itemR(boids, "land_max_speed")
col.itemR(boids, "land_jump_speed")
col.itemR(boids, "land_max_acc", slider="True")
col.itemR(boids, "land_max_ave", slider="True")
col.itemR(boids, "land_personal_space")
col.itemR(boids, "land_stick_force")
row = layout.row()
row.template_list(psys, "keyed_targets", psys, "active_keyed_target_index")
col = row.column(align=True)
col.itemL(text="Battle:")
col.itemR(boids, "health")
col.itemR(boids, "strength")
col.itemR(boids, "aggression")
col.itemR(boids, "accuracy")
col.itemR(boids, "range")
col = row.column()
col.itemL(text="Misc:")
col.itemR(part, "gravity")
col.itemR(boids, "banking", slider=True)
col.itemR(boids, "height", slider=True)
if part.physics_type=='NEWTON':
sub.itemR(part, "size_deflect")
sub.itemR(part, "die_on_collision")
sub.itemR(part, "sticky")
elif part.physics_type=='KEYED' or part.physics_type=='BOIDS':
if part.physics_type=='BOIDS':
layout.itemL(text="Relations:")
row = layout.row()
row.template_list(psys, "targets", psys, "active_particle_target_index")
col = row.column()
subrow = col.row()
subcol = subrow.column(align=True)
subcol.itemO("particle.new_keyed_target", icon="ICON_ZOOMIN", text="")
subcol.itemO("particle.remove_keyed_target", icon="ICON_ZOOMOUT", text="")
subcol.itemO("particle.new_target", icon="ICON_ZOOMIN", text="")
subcol.itemO("particle.remove_target", icon="ICON_ZOOMOUT", text="")
subrow = col.row()
subcol = subrow.column(align=True)
subcol.itemO("particle.keyed_target_move_up", icon="VICON_MOVE_UP", text="")
subcol.itemO("particle.keyed_target_move_down", icon="VICON_MOVE_DOWN", text="")
subcol.itemO("particle.target_move_up", icon="VICON_MOVE_UP", text="")
subcol.itemO("particle.target_move_down", icon="VICON_MOVE_DOWN", text="")
key = psys.active_keyed_target
key = psys.active_particle_target
if key:
row = layout.row()
col = row.column()
#doesn't work yet
#col.red_alert = key.valid
col.itemR(key, "object", text="")
col.itemR(key, "system", text="System")
col = row.column();
col.active = psys.keyed_timing
col.itemR(key, "time")
col.itemR(key, "duration")
if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
if part.physics_type=='KEYED':
col = row.column()
#doesn't work yet
#col.red_alert = key.valid
col.itemR(key, "object", text="")
col.itemR(key, "system", text="System")
col = row.column();
col.active = psys.keyed_timing
col.itemR(key, "time")
col.itemR(key, "duration")
else:
subrow = row.row()
#doesn't work yet
#subrow.red_alert = key.valid
subrow.itemR(key, "object", text="")
subrow.itemR(key, "system", text="System")
layout.itemR(key, "mode", expand=True)
sub.itemR(part, "size_deflect")
sub.itemR(part, "die_on_collision")
sub.itemR(part, "sticky")
class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
__idname__ = "PARTICLE_PT_boidbrain"
__label__ = "Boid Brain"
def poll(self, context):
psys = context.particle_system
if psys==None: return False
if psys.settings==None: return False
return psys.settings.physics_type=='BOIDS'
def draw(self, context):
boids = context.particle_system.settings.boids
layout = self.layout
# Currently boids can only use the first state so these are commented out for now.
#row = layout.row()
#row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
#col = row.row()
#subrow = col.row(align=True)
#subrow.itemO("boid.boidstate_add", icon="ICON_ZOOMIN", text="")
#subrow.itemO("boid.boidstate_del", icon="ICON_ZOOMOUT", text="")
#subrow = row.row(align=True)
#subrow.itemO("boid.boidstate_move_up", icon="VICON_MOVE_UP", text="")
#subrow.itemO("boid.boidstate_move_down", icon="VICON_MOVE_DOWN", text="")
state = boids.active_boid_state
#layout.itemR(state, "name", text="State name")
row = layout.row()
row.itemR(state, "ruleset_type")
if state.ruleset_type=='FUZZY':
row.itemR(state, "rule_fuzziness", slider=True)
else:
row.itemL(text="")
row = layout.row()
row.template_list(state, "rules", state, "active_boid_rule_index")
col = row.column()
subrow = col.row()
subcol = subrow.column(align=True)
subcol.item_menu_enumO("boid.boidrule_add", "type", icon="ICON_ZOOMIN", text="")
subcol.itemO("boid.boidrule_del", icon="ICON_ZOOMOUT", text="")
subrow = col.row()
subcol = subrow.column(align=True)
subcol.itemO("boid.boidrule_move_up", icon="VICON_MOVE_UP", text="")
subcol.itemO("boid.boidrule_move_down", icon="VICON_MOVE_DOWN", text="")
rule = state.active_boid_rule
if rule:
row = layout.row()
row.itemR(rule, "name", text="")
#somebody make nice icons for boids here please! -jahka
row.itemR(rule, "in_air", icon="VICON_MOVE_UP", text="")
row.itemR(rule, "on_land", icon="VICON_MOVE_DOWN", text="")
row = layout.row()
if rule.type == 'GOAL':
row.itemR(rule, "object")
row = layout.row()
row.itemR(rule, "predict")
elif rule.type == 'AVOID':
row.itemR(rule, "object")
row = layout.row()
row.itemR(rule, "predict")
row.itemR(rule, "fear_factor")
elif rule.type == 'FOLLOW_PATH':
row.itemL(text="Not yet functional.")
elif rule.type == 'AVOID_COLLISION':
row.itemR(rule, "boids")
row.itemR(rule, "deflectors")
row.itemR(rule, "look_ahead")
elif rule.type == 'FOLLOW_LEADER':
row.itemR(rule, "object", text="")
row.itemR(rule, "distance")
row = layout.row()
row.itemR(rule, "line")
subrow = row.row()
subrow.active = rule.line
subrow.itemR(rule, "queue_size")
elif rule.type == 'AVERAGE_SPEED':
row.itemR(rule, "speed", slider=True)
row.itemR(rule, "wander", slider=True)
row.itemR(rule, "level", slider=True)
elif rule.type == 'FIGHT':
row.itemR(rule, "distance")
row.itemR(rule, "flee_distance")
class PARTICLE_PT_render(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_render"
@@ -596,6 +759,38 @@ class PARTICLE_PT_children(ParticleButtonsPanel):
sub = split.column()
sub.itemR(part, "kink_shape", slider=True)
class PARTICLE_PT_effectors(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_effectors"
__label__ = "Effectors"
__default_closed__ = True
def poll(self, context):
psys = context.particle_system
if psys==None: return False
if psys.settings==None: return False
return True;
def draw(self, context):
layout = self.layout
psys = context.particle_system
part = psys.settings
layout.itemR(part, "effector_group")
layout.itemR(part, "eweight_all", slider=True)
layout.itemS()
layout.itemR(part, "eweight_spherical", slider=True)
layout.itemR(part, "eweight_vortex", slider=True)
layout.itemR(part, "eweight_magnetic", slider=True)
layout.itemR(part, "eweight_wind", slider=True)
layout.itemR(part, "eweight_curveguide", slider=True)
layout.itemR(part, "eweight_texture", slider=True)
layout.itemR(part, "eweight_harmonic", slider=True)
layout.itemR(part, "eweight_charge", slider=True)
layout.itemR(part, "eweight_lennardjones", slider=True)
class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_vertexgroups"
__label__ = "Vertexgroups"
@@ -667,7 +862,9 @@ bpy.types.register(PARTICLE_PT_cache)
bpy.types.register(PARTICLE_PT_emission)
bpy.types.register(PARTICLE_PT_initial)
bpy.types.register(PARTICLE_PT_physics)
bpy.types.register(PARTICLE_PT_boidbrain)
bpy.types.register(PARTICLE_PT_render)
bpy.types.register(PARTICLE_PT_draw)
bpy.types.register(PARTICLE_PT_children)
bpy.types.register(PARTICLE_PT_effectors)
bpy.types.register(PARTICLE_PT_vertexgroups)

View File

@@ -53,6 +53,11 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
sub.itemR(field, "planar")
sub.itemR(field, "surface")
if field.type == "BOID":
sub.itemR(field, "strength")
sub = split.column()
sub.itemR(field, "surface")
if field.type == "MAGNET":
sub.itemR(field, "strength")
sub = split.column()
@@ -75,7 +80,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel):
sub.itemR(field, "root_coordinates")
sub.itemR(field, "force_2d")
if field.type in ("HARMONIC", "SPHERICAL", "CHARGE", "WIND", "VORTEX", "TEXTURE", "MAGNET"):
if field.type in ("HARMONIC", "SPHERICAL", "CHARGE", "WIND", "VORTEX", "TEXTURE", "MAGNET", "BOID"):
layout.itemS()

View File

@@ -0,0 +1,62 @@
/* BKE_particle.h
*
*
* $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 by Janne Karhu.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BKE_BOIDS_H
#define BKE_BOIDS_H
#include "DNA_boid_types.h"
typedef struct BoidBrainData {
Scene *scene;
struct Object *ob;
struct ParticleSystem *psys;
struct ParticleSettings *part;
float timestep, cfra, dfra;
float wanted_co[3], wanted_speed;
/* Goal stuff */
struct Object *goal_ob;
float goal_co[3];
float goal_nor[3];
float goal_priority;
} BoidBrainData;
void boids_precalc_rules(struct ParticleSettings *part, float cfra);
void boid_brain(BoidBrainData *bbd, int p, struct ParticleData *pa);
void boid_body(BoidBrainData *bbd, struct ParticleData *pa);
void boid_default_settings(BoidSettings *boids);
BoidRule *boid_new_rule(int type);
BoidState *boid_new_state(BoidSettings *boids);
BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state);
void boid_free_settings(BoidSettings *boids);
BoidSettings *boid_copy_settings(BoidSettings *boids);
BoidState *boid_get_current_state(BoidSettings *boids);
#endif

View File

@@ -95,16 +95,6 @@ typedef struct ParticleTexture{
float rough1, rough2, roughe; /* used in path caching */
} ParticleTexture;
typedef struct BoidVecFunc{
void (*Addf)(float *v, float *v1, float *v2);
void (*Subf)(float *v, float *v1, float *v2);
void (*Mulf)(float *v, float f);
float (*Length)(float *v);
float (*Normalize)(float *v);
float (*Inpf)(float *v1, float *v2);
void (*Copyf)(float *v1, float *v2);
} BoidVecFunc;
typedef struct ParticleSeam{
float v0[3], v1[3];
float nor[3], dir[3], tan[3];
@@ -209,6 +199,19 @@ typedef struct ParticleBillboardData
}
ParticleBillboardData;
/* container for moving data between deflet_particle and particle_intersect_face */
typedef struct ParticleCollision
{
struct Object *ob, *ob_t; // collided and current objects
struct CollisionModifierData *md; // collision modifier for ob_t;
float nor[3]; // normal at collision point
float vel[3]; // velocity of collision point
float co1[3], co2[3]; // ray start and end points
float ray_len; // original length of co2-co1, needed for collision time evaluation
float t; // time of previous collision, needed for substracting face velocity
}
ParticleCollision;
/* ----------- functions needed outside particlesystem ---------------- */
/* particle.c */
int count_particles(struct ParticleSystem *psys);
@@ -231,6 +234,7 @@ int psys_ob_has_hair(struct Object *ob);
int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys);
int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys);
void psys_free_boid_rules(struct ListBase *list);
void psys_free_settings(struct ParticleSettings *part);
void free_child_path_cache(struct ParticleSystem *psys);
void psys_free_path_cache(struct ParticleSystem *psys);
@@ -288,6 +292,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
/* particle_system.c */
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
void psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
@@ -298,6 +303,8 @@ void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
void psys_end_temp_pointcache(struct ParticleSystem *psys);
void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra);
void psys_check_boid_data(struct ParticleSystem *psys);
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* ----------- functions needed only inside particlesystem ------------ */
@@ -321,11 +328,13 @@ float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int
void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time);
int psys_intersect_dm(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint);
void particle_intersect_face(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit);
void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor);
/* particle_system.c */
void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd);
int effector_find_co(struct Scene *scene, float *pco, struct SurfaceModifierData *sur, struct Object *ob, struct PartDeflect *pd, float *co, float *nor, float *vel, int *index);
void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float *texco, float *force_field, float *vel,float framestep, float cfra);
void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,7 @@
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_boid_types.h"
#include "DNA_curve_types.h"
#include "DNA_camera_types.h"
#include "DNA_ID.h"
@@ -555,6 +556,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
GroupObject *go;
for(; psys; psys=psys->next) {
BoidRule *rule = NULL;
BoidState *state = NULL;
ParticleSettings *part= psys->part;
dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
@@ -562,16 +565,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if(!psys_check_enabled(ob, psys))
continue;
if(part->phystype==PART_PHYS_KEYED) {
KeyedParticleTarget *kpt = psys->keyed_targets.first;
if(ELEM(part->phystype,PART_PHYS_KEYED,PART_PHYS_BOIDS)) {
ParticleTarget *pt = psys->targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->ob && BLI_findlink(&kpt->ob->particlesystem, kpt->psys-1)) {
node2 = dag_get_node(dag, kpt->ob);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Keyed Physics");
for(; pt; pt=pt->next) {
if(pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys-1)) {
node2 = dag_get_node(dag, pt->ob);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Targets");
}
else
break;
}
}
@@ -589,33 +590,47 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
}
}
if(psys->effectors.first)
psys_end_effectors(psys);
psys_end_effectors(psys);
psys_init_effectors(scene, ob, psys->part->eff_group, psys);
if(psys->effectors.first) {
for(nec= psys->effectors.first; nec; nec= nec->next) {
Object *ob1= nec->ob;
for(nec= psys->effectors.first; nec; nec= nec->next) {
Object *ob1= nec->ob;
if(nec->type & PSYS_EC_EFFECTOR) {
node2 = dag_get_node(dag, ob1);
if(ob1->pd->forcefield==PFIELD_GUIDE)
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
else
dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Particle Field");
}
else if(nec->type & PSYS_EC_DEFLECT) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Collision");
}
else if(nec->type & PSYS_EC_PARTICLE) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Field");
}
if(nec->type & PSYS_EC_REACTOR) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Reactor");
if(nec->type & PSYS_EC_EFFECTOR) {
node2 = dag_get_node(dag, ob1);
if(ob1->pd->forcefield==PFIELD_GUIDE)
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Field");
else
dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Particle Field");
}
else if(nec->type & PSYS_EC_DEFLECT) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Collision");
}
else if(nec->type & PSYS_EC_PARTICLE) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Field");
}
if(nec->type & PSYS_EC_REACTOR) {
node2 = dag_get_node(dag, ob1);
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Reactor");
}
}
if(part->boids) {
for(state = part->boids->states.first; state; state=state->next) {
for(rule = state->rules.first; rule; rule=rule->next) {
Object *ruleob = NULL;
if(rule->type==eBoidRuleType_Avoid)
ruleob = ((BoidRuleGoalAvoid*)rule)->ob;
else if(rule->type==eBoidRuleType_FollowLeader)
ruleob = ((BoidRuleFollowLeader*)rule)->ob;
if(ruleob) {
node2 = dag_get_node(dag, ruleob);
dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
}
}
}
}
@@ -2070,7 +2085,6 @@ static void dag_object_time_update_flags(Object *ob)
}
}
}
/* flag all objects that need recalc, for changes in time for example */
void DAG_scene_update_flags(Scene *scene, unsigned int lay)
{

View File

@@ -505,6 +505,9 @@ void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, flo
VecAddf(field,field,mag_vec);
break;
}
case PFIELD_BOID:
/* Boid field is handled completely in boids code. */
break;
}
}

View File

@@ -6113,9 +6113,14 @@ static void surfaceModifier_freeData(ModifierData *md)
MEM_freeN(surmd->bvhtree);
}
if(surmd->dm)
surmd->dm->release(surmd->dm);
surmd->dm->release(surmd->dm);
if(surmd->x)
MEM_freeN(surmd->x);
if(surmd->v)
MEM_freeN(surmd->v);
surmd->bvhtree = NULL;
surmd->dm = NULL;
}
@@ -6128,7 +6133,7 @@ static int surfaceModifier_dependsOnTime(ModifierData *md)
static void surfaceModifier_deformVerts(
ModifierData *md, Object *ob, DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
{
SurfaceModifierData *surmd = (SurfaceModifierData*) md;
unsigned int numverts = 0, i = 0;
@@ -6148,14 +6153,47 @@ static void surfaceModifier_deformVerts(
if(surmd->dm)
{
int init = 0;
float *vec;
MVert *x, *v;
CDDM_apply_vert_coords(surmd->dm, vertexCos);
CDDM_calc_normals(surmd->dm);
numverts = surmd->dm->getNumVerts ( surmd->dm );
/* convert to global coordinates */
for(i = 0; i<numverts; i++)
Mat4MulVecfl(ob->obmat, CDDM_get_vert(surmd->dm, i)->co);
if(numverts != surmd->numverts || surmd->x == NULL || surmd->v == NULL || md->scene->r.cfra != surmd->cfra+1) {
if(surmd->x) {
MEM_freeN(surmd->x);
surmd->x = NULL;
}
if(surmd->v) {
MEM_freeN(surmd->v);
surmd->v = NULL;
}
surmd->x = MEM_callocN(numverts * sizeof(MVert), "MVert");
surmd->v = MEM_callocN(numverts * sizeof(MVert), "MVert");
surmd->numverts = numverts;
init = 1;
}
/* convert to global coordinates and calculate velocity */
for(i = 0, x = surmd->x, v = surmd->v; i<numverts; i++, x++, v++) {
vec = CDDM_get_vert(surmd->dm, i)->co;
Mat4MulVecfl(ob->obmat, vec);
if(init)
v->co[0] = v->co[1] = v->co[2] = 0.0f;
else
VecSubf(v->co, vec, x->co);
VecCopyf(x->co, vec);
}
surmd->cfra = md->scene->r.cfra;
if(surmd->bvhtree)
free_bvhtree_from_mesh(surmd->bvhtree);

View File

@@ -42,6 +42,7 @@
#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_boid_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
@@ -429,11 +430,13 @@ void unlink_object(Scene *scene, Object *ob)
if(obt->particlesystem.first) {
ParticleSystem *tpsys= obt->particlesystem.first;
for(; tpsys; tpsys=tpsys->next) {
KeyedParticleTarget *kpt = tpsys->keyed_targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->ob==ob) {
BLI_remlink(&tpsys->keyed_targets, kpt);
MEM_freeN(kpt);
BoidState *state = NULL;
BoidRule *rule = NULL;
ParticleTarget *pt = tpsys->targets.first;
for(; pt; pt=pt->next) {
if(pt->ob==ob) {
pt->ob = NULL;
obt->recalc |= OB_RECALC_DATA;
break;
}
@@ -458,6 +461,22 @@ void unlink_object(Scene *scene, Object *ob)
}
}
}
if(tpsys->part->boids) {
for(state = tpsys->part->boids->states.first; state; state=state->next) {
for(rule = state->rules.first; rule; rule=rule->next) {
if(rule->type==eBoidRuleType_Avoid) {
BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*)rule;
if(gabr->ob==ob)
gabr->ob= NULL;
}
else if(rule->type==eBoidRuleType_FollowLeader) {
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*)rule;
if(flbr->ob==ob)
flbr->ob= NULL;
}
}
}
}
}
if(ob->pd)
obt->recalc |= OB_RECALC_DATA;
@@ -1063,8 +1082,14 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
psysn->soft->particles = psysn;
}
if(psys->keyed_targets.first)
BLI_duplicatelist(&psysn->keyed_targets, &psys->keyed_targets);
if(psys->particles->boid) {
psysn->particles->boid = MEM_dupallocN(psys->particles->boid);
for(a=1, pa=psysn->particles+1; a<psysn->totpart; a++, pa++)
pa->boid = (pa-1)->boid + 1;
}
if(psys->targets.first)
BLI_duplicatelist(&psysn->targets, &psys->targets);
psysn->pathcache= NULL;
psysn->childcache= NULL;
@@ -2369,10 +2394,17 @@ void object_handle_update(Scene *scene, Object *ob)
if(ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
DerivedMesh *dm;
ob->transflag &= ~OB_DUPLIPARTS;
psys= ob->particlesystem.first;
while(psys) {
if(psys_check_enabled(ob, psys)) {
/* check use of dupli objects here */
if(psys->part && psys->part->draw_as == PART_DRAW_REND &&
((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob)
|| (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
ob->transflag |= OB_DUPLIPARTS;
particle_system_update(scene, ob, psys);
psys= psys->next;
}

View File

@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
#include "DNA_boid_types.h"
#include "DNA_particle_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -58,6 +59,7 @@
#include "BKE_anim.h"
#include "BKE_boids.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_lattice.h"
@@ -355,10 +357,13 @@ void psys_free_settings(ParticleSettings *part)
MEM_freeN(part->pd);
part->pd = NULL;
}
if(part->pd2) {
MEM_freeN(part->pd2);
part->pd2 = NULL;
}
boid_free_settings(part->boids);
}
void free_hair(ParticleSystem *psys, int softbody)
@@ -439,6 +444,9 @@ void psys_free(Object *ob, ParticleSystem * psys)
psys->free_edit(psys);
if(psys->particles){
if(psys->particles->boid)
MEM_freeN(psys->particles->boid);
MEM_freeN(psys->particles);
psys->particles = 0;
psys->totpart = 0;
@@ -479,8 +487,10 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->pointcache)
BKE_ptcache_free(psys->pointcache);
if(psys->keyed_targets.first)
BLI_freelistN(&psys->keyed_targets);
if(psys->targets.first)
BLI_freelistN(&psys->targets);
BLI_kdtree_free(psys->tree);
MEM_freeN(psys);
}
@@ -1043,21 +1053,21 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey-1].time - pind->kkey[0]->time);
if(psys->part->phystype==PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
KeyedParticleTarget *kpt = psys->keyed_targets.first;
ParticleTarget *pt = psys->targets.first;
kpt=kpt->next;
pt=pt->next;
while(kpt && pa->time + kpt->time < real_t)
kpt= kpt->next;
while(pt && pa->time + pt->time < real_t)
pt= pt->next;
if(kpt) {
kpt=kpt->prev;
if(pt) {
pt=pt->prev;
if(pa->time + kpt->time + kpt->duration > real_t)
real_t = pa->time + kpt->time;
if(pa->time + pt->time + pt->duration > real_t)
real_t = pa->time + pt->time;
}
else
real_t = pa->time + ((KeyedParticleTarget*)psys->keyed_targets.last)->time;
real_t = pa->time + ((ParticleTarget*)psys->targets.last)->time;
}
CLAMP(real_t, pa->time, pa->dietime);
@@ -3028,7 +3038,12 @@ void object_add_particle_system(Scene *scene, Object *ob)
psys->pointcache = BKE_ptcache_add();
BLI_addtail(&ob->particlesystem, psys);
psys->part = psys_new_settings("PSys", NULL);
psys->part = psys_new_settings("ParticleSettings", NULL);
if(BLI_countlist(&ob->particlesystem)>1)
sprintf(psys->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
else
strcpy(psys->name, "ParticleSystem");
md= modifier_new(eModifierType_ParticleSystem);
sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
@@ -3099,14 +3114,8 @@ static void default_particle_settings(ParticleSettings *part)
part->reactevent= PART_EVENT_DEATH;
part->disp=100;
part->from= PART_FROM_FACE;
part->nbetween= 4;
part->boidneighbours= 5;
part->normfac= 1.0f;
part->max_vel = 10.0f;
part->average_vel = 0.3f;
part->max_tan_acc = 0.2f;
part->max_lat_acc = 1.0f;
part->reactshape=1.0f;
@@ -3136,13 +3145,9 @@ static void default_particle_settings(ParticleSettings *part)
part->keyed_loops = 1;
part->banking=1.0;
part->max_bank=1.0;
for(i=0; i<10; i++)
part->effector_weight[i]=1.0f;
for(i=0; i<BOID_TOT_RULES; i++){
part->boidrule[i]=(char)i;
part->boidfac[i]=0.5;
}
#if 0 // XXX old animation system
part->ipo = NULL;
@@ -3176,6 +3181,8 @@ ParticleSettings *psys_copy_settings(ParticleSettings *part)
partn= copy_libblock(part);
if(partn->pd) partn->pd= MEM_dupallocN(part->pd);
if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2);
partn->boids = boid_copy_settings(part->boids);
return partn;
}

File diff suppressed because it is too large Load Diff

View File

@@ -52,9 +52,13 @@ void BLI_kdtree_balance(KDTree *tree);
/* Find nearest returns index, and -1 if no node is found.
* Find n nearest returns number of points found, with results in nearest.
* Normal is optional. */
/* Normal is optional, but if given will limit results to points in normal direction from co. */
int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest);
int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTreeNearest *nearest);
/* Range search returns number of points found, with results in nearest */
/* Normal is optional, but if given will limit results to points in normal direction from co. */
/* Remember to free nearest after use! */
int BLI_kdtree_range_search(KDTree *tree, float range, float *co, float *nor, KDTreeNearest **nearest);
#endif

View File

@@ -130,7 +130,7 @@ void BLI_kdtree_balance(KDTree *tree)
tree->root= kdtree_balance(tree->nodes, tree->totnode, 0);
}
static float squared_distance(float *v1, float *v2, float *n1, float *n2)
static float squared_distance(float *v2, float *v1, float *n1, float *n2)
{
float d[3], dist;
@@ -140,7 +140,8 @@ static float squared_distance(float *v1, float *v2, float *n1, float *n2)
dist= d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
if(n1 && n2 && n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2] < 0.0f)
//if(n1 && n2 && n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2] < 0.0f)
if(n2 && d[0]*n2[0] + d[1]*n2[1] + d[2]*n2[2] < 0.0f)
dist *= 10.0f;
return dist;
@@ -336,3 +337,111 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, float *co, float *nor, KDTree
return found;
}
int range_compare(const void * a, const void * b)
{
const KDTreeNearest *kda = a;
const KDTreeNearest *kdb = b;
if(kda->dist < kdb->dist)
return -1;
else if(kda->dist > kdb->dist)
return 1;
else
return 0;
}
static void add_in_range(KDTreeNearest **ptn, int found, int *totfoundstack, int index, float dist, float *co)
{
KDTreeNearest *to;
if(found+1 > *totfoundstack) {
KDTreeNearest *temp=MEM_callocN((*totfoundstack+50)*sizeof(KDTreeNode), "psys_treefoundstack");
memcpy(temp, *ptn, *totfoundstack * sizeof(KDTreeNearest));
if(*ptn)
MEM_freeN(*ptn);
*ptn = temp;
*totfoundstack+=50;
}
to = (*ptn) + found;
to->index = index;
to->dist = sqrt(dist);
VecCopyf(to->co, co);
}
int BLI_kdtree_range_search(KDTree *tree, float range, float *co, float *nor, KDTreeNearest **nearest)
{
KDTreeNode *root, *node=0;
KDTreeNode **stack, *defaultstack[100];
KDTreeNearest *foundstack=NULL;
float range2 = range*range, dist2;
int i, totstack, cur=0, found=0, totfoundstack=0;
if(!tree || !tree->root)
return 0;
stack= defaultstack;
totstack= 100;
root= tree->root;
if(co[root->d] + range < root->co[root->d]) {
if(root->left)
stack[cur++]=root->left;
}
else if(co[root->d] - range > root->co[root->d]) {
if(root->right)
stack[cur++]=root->right;
}
else {
dist2 = squared_distance(root->co, co, root->nor, nor);
if(dist2 <= range2)
add_in_range(&foundstack, found++, &totfoundstack, root->index, dist2, root->co);
if(root->left)
stack[cur++]=root->left;
if(root->right)
stack[cur++]=root->right;
}
while(cur--) {
node=stack[cur];
if(co[node->d] + range < node->co[node->d]) {
if(node->left)
stack[cur++]=node->left;
}
else if(co[node->d] - range > node->co[node->d]) {
if(node->right)
stack[cur++]=node->right;
}
else {
dist2 = squared_distance(node->co, co, node->nor, nor);
if(dist2 <= range2)
add_in_range(&foundstack, found++, &totfoundstack, node->index, dist2, node->co);
if(node->left)
stack[cur++]=node->left;
if(node->right)
stack[cur++]=node->right;
}
if(cur+3 > totstack){
KDTreeNode **temp=MEM_callocN((totstack+100)*sizeof(KDTreeNode*), "psys_treestack");
memcpy(temp,stack,totstack*sizeof(KDTreeNode*));
if(stack != defaultstack)
MEM_freeN(stack);
stack=temp;
totstack+=100;
}
}
if(stack != defaultstack)
MEM_freeN(stack);
if(found)
qsort(foundstack, found, sizeof(KDTreeNearest), range_compare);
*nearest = foundstack;
return found;
}

View File

@@ -53,6 +53,7 @@
#include "DNA_armature_types.h"
#include "DNA_ID.h"
#include "DNA_actuator_types.h"
#include "DNA_boid_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
@@ -2990,6 +2991,29 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
if(part->boids) {
BoidState *state = part->boids->states.first;
BoidRule *rule;
for(; state; state=state->next) {
rule = state->rules.first;
for(; rule; rule=rule->next)
switch(rule->type) {
case eBoidRuleType_Goal:
case eBoidRuleType_Avoid:
{
BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid*)rule;
brga->ob = newlibadr(fd, part->id.lib, brga->ob);
break;
}
case eBoidRuleType_FollowLeader:
{
BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader*)rule;
brfl->ob = newlibadr(fd, part->id.lib, brfl->ob);
break;
}
}
}
}
part->id.flag -= LIB_NEEDLINK;
}
part= part->id.next;
@@ -3001,6 +3025,19 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
part->adt= newdataadr(fd, part->adt);
part->pd= newdataadr(fd, part->pd);
part->pd2= newdataadr(fd, part->pd2);
part->boids= newdataadr(fd, part->boids);
if(part->boids) {
BoidState *state;
link_list(fd, &part->boids->states);
for(state=part->boids->states.first; state; state=state->next) {
link_list(fd, &state->rules);
link_list(fd, &state->conditions);
link_list(fd, &state->actions);
}
}
}
static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles)
@@ -3015,10 +3052,10 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
psys->part = newlibadr_us(fd, id->lib, psys->part);
if(psys->part) {
KeyedParticleTarget *kpt = psys->keyed_targets.first;
ParticleTarget *pt = psys->targets.first;
for(; kpt; kpt=kpt->next)
kpt->ob=newlibadr(fd, id->lib, kpt->ob);
for(; pt; pt=pt->next)
pt->ob=newlibadr(fd, id->lib, pt->ob);
psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
@@ -3042,24 +3079,38 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
static void direct_link_particlesystems(FileData *fd, ListBase *particles)
{
ParticleSystem *psys;
ParticleData *pa;
int a;
for(psys=particles->first; psys; psys=psys->next) {
psys->particles=newdataadr(fd,psys->particles);
if(psys->particles && psys->particles->hair){
ParticleData *pa = psys->particles;
for(a=0; a<psys->totpart; a++, pa++)
for(a=0,pa=psys->particles; a<psys->totpart; a++, pa++)
pa->hair=newdataadr(fd,pa->hair);
}
if(psys->particles && psys->particles->keys){
ParticleData *pa = psys->particles;
for(a=0; a<psys->totpart; a++, pa++) {
for(a=0,pa=psys->particles; a<psys->totpart; a++, pa++) {
pa->keys= NULL;
pa->totkey= 0;
}
psys->flag &= ~PSYS_KEYED;
}
if(psys->particles->boid) {
pa = psys->particles;
pa->boid = newdataadr(fd, pa->boid);
for(a=1,pa++; a<psys->totpart; a++, pa++)
pa->boid = (pa-1)->boid + 1;
}
else {
for(a=0,pa=psys->particles; a<psys->totpart; a++, pa++)
pa->boid = NULL;
}
psys->child=newdataadr(fd,psys->child);
psys->effectors.first=psys->effectors.last=0;
@@ -3076,7 +3127,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
direct_link_pointcache(fd, sb->pointcache);
}
link_list(fd, &psys->keyed_targets);
link_list(fd, &psys->targets);
psys->edit = 0;
psys->free_edit = NULL;
@@ -3089,6 +3140,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
psys->pointcache= newdataadr(fd, psys->pointcache);
if(psys->pointcache)
direct_link_pointcache(fd, psys->pointcache);
psys->tree = NULL;
}
return;
}
@@ -3649,6 +3702,9 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
surmd->dm = NULL;
surmd->bvhtree = NULL;
surmd->x = NULL;
surmd->v = NULL;
surmd->numverts = 0;
}
else if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
@@ -8541,7 +8597,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
psys->pointcache = BKE_ptcache_add();
part = psys->part = psys_new_settings("PSys", main);
part = psys->part = psys_new_settings("ParticleSettings", main);
/* needed for proper libdata lookup */
oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);

View File

@@ -93,6 +93,7 @@ Any case: direct data is ALWAYS after the lib block
#include "DNA_armature_types.h"
#include "DNA_action_types.h"
#include "DNA_actuator_types.h"
#include "DNA_boid_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_cloth_types.h"
@@ -550,6 +551,39 @@ static void write_userdef(WriteData *wd)
}
}
static void write_boid_state(WriteData *wd, BoidState *state)
{
BoidRule *rule = state->rules.first;
//BoidCondition *cond = state->conditions.first;
writestruct(wd, DATA, "BoidState", 1, state);
for(; rule; rule=rule->next) {
switch(rule->type) {
case eBoidRuleType_Goal:
case eBoidRuleType_Avoid:
writestruct(wd, DATA, "BoidRuleGoalAvoid", 1, rule);
break;
case eBoidRuleType_AvoidCollision:
writestruct(wd, DATA, "BoidRuleAvoidCollision", 1, rule);
break;
case eBoidRuleType_FollowLeader:
writestruct(wd, DATA, "BoidRuleFollowLeader", 1, rule);
break;
case eBoidRuleType_AverageSpeed:
writestruct(wd, DATA, "BoidRuleAverageSpeed", 1, rule);
break;
case eBoidRuleType_Fight:
writestruct(wd, DATA, "BoidRuleFight", 1, rule);
break;
default:
writestruct(wd, DATA, "BoidRule", 1, rule);
break;
}
}
//for(; cond; cond=cond->next)
// writestruct(wd, DATA, "BoidCondition", 1, cond);
}
/* TODO: replace *cache with *cachelist once it's coded */
#define PTCACHE_WRITE_PSYS 0
#define PTCACHE_WRITE_CLOTH 1
@@ -582,6 +616,15 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
if (part->adt) write_animdata(wd, part->adt);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
if(part->boids && part->phystype == PART_PHYS_BOIDS) {
BoidState *state = part->boids->states.first;
writestruct(wd, DATA, "BoidSettings", 1, part->boids);
for(; state; state=state->next)
write_boid_state(wd, state);
}
}
part= part->id.next;
}
@@ -589,7 +632,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
static void write_particlesystems(WriteData *wd, ListBase *particles)
{
ParticleSystem *psys= particles->first;
KeyedParticleTarget *kpt;
ParticleTarget *pt;
int a;
for(; psys; psys=psys->next) {
@@ -604,10 +647,13 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
for(a=0; a<psys->totpart; a++, pa++)
writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair);
}
if(psys->particles->boid && psys->part->phystype == PART_PHYS_BOIDS)
writestruct(wd, DATA, "BoidData", psys->totpart, psys->particles->boid);
}
kpt = psys->keyed_targets.first;
for(; kpt; kpt=kpt->next)
writestruct(wd, DATA, "KeyedParticleTarget", 1, kpt);
pt = psys->targets.first;
for(; pt; pt=pt->next)
writestruct(wd, DATA, "ParticleTarget", 1, pt);
if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
writestruct(wd, DATA, "SoftBody", 1, psys->soft);

View File

@@ -32,6 +32,7 @@
/* operators */
void ED_operatortypes_boids(void);
void ED_operatortypes_pointcache(void);
void ED_operatortypes_fluid(void);
//void ED_keymap_pointcache(struct wmWindowManager *wm);

View File

@@ -0,0 +1,433 @@
/**
* $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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 Janne Karhu.
* All rights reserved.
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
//#include <stdlib.h>
//#include <string.h>
//
#include "MEM_guardedalloc.h"
#include "DNA_boid_types.h"
#include "DNA_particle_types.h"
//#include "DNA_curve_types.h"
#include "DNA_object_types.h"
//#include "DNA_material_types.h"
//#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
//#include "DNA_world_types.h"
#include "BKE_boids.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
//#include "BKE_font.h"
//#include "BKE_library.h"
//#include "BKE_main.h"
//#include "BKE_material.h"
#include "BKE_particle.h"
//#include "BKE_texture.h"
//#include "BKE_utildefines.h"
//#include "BKE_world.h"
//#include "BLI_editVert.h"
#include "BLI_listbase.h"
//
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
//#include "ED_curve.h"
//#include "ED_mesh.h"
//
//#include "buttons_intern.h" // own include
/************************ add/del boid rule operators *********************/
static int boidrule_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob= ptr.id.data;
ParticleSettings *part;
int type= RNA_enum_get(op->ptr, "type");
BoidRule *rule;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
part = psys->part;
state = boid_get_current_state(part->boids);
for(rule=state->rules.first; rule; rule=rule->next)
rule->flag &= ~BOIDRULE_CURRENT;
rule = boid_new_rule(type);
rule->flag |= BOIDRULE_CURRENT;
BLI_addtail(&state->rules, rule);
psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void BOID_OT_boidrule_add(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Add Boid Rule";
ot->description = "Add a boid rule to the current boid state.";
ot->idname= "BOID_OT_boidrule_add";
/* api callbacks */
ot->invoke= WM_menu_invoke;
ot->exec= boidrule_add_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "type", boidrule_type_items, 0, "Type", "");
}
static int boidrule_del_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
BoidRule *rule;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
state = boid_get_current_state(psys->part->boids);
for(rule=state->rules.first; rule; rule=rule->next) {
if(rule->flag & BOIDRULE_CURRENT) {
BLI_remlink(&state->rules, rule);
MEM_freeN(rule);
break;
}
}
rule = state->rules.first;
if(rule)
rule->flag |= BOIDRULE_CURRENT;
DAG_scene_sort(scene);
psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void BOID_OT_boidrule_del(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Remove Boid Rule";
ot->idname= "BOID_OT_boidrule_del";
/* api callbacks */
ot->exec= boidrule_del_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ move up/down boid rule operators *********************/
static int boidrule_move_up_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
BoidRule *rule;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
state = boid_get_current_state(psys->part->boids);
for(rule = state->rules.first; rule; rule=rule->next) {
if(rule->flag & BOIDRULE_CURRENT && rule->prev) {
BLI_remlink(&state->rules, rule);
BLI_insertlink(&state->rules, rule->prev->prev, rule);
psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
break;
}
}
return OPERATOR_FINISHED;
}
void BOID_OT_boidrule_move_up(wmOperatorType *ot)
{
ot->name= "Move Up Boid Rule";
ot->description= "Move boid rule up in the list.";
ot->idname= "BOID_OT_boidrule_move_up";
ot->exec= boidrule_move_up_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int boidrule_move_down_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
BoidRule *rule;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
state = boid_get_current_state(psys->part->boids);
for(rule = state->rules.first; rule; rule=rule->next) {
if(rule->flag & BOIDRULE_CURRENT && rule->next) {
BLI_remlink(&state->rules, rule);
BLI_insertlink(&state->rules, rule->next, rule);
psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
break;
}
}
return OPERATOR_FINISHED;
}
void BOID_OT_boidrule_move_down(wmOperatorType *ot)
{
ot->name= "Move Down Boid Rule";
ot->description= "Move boid rule down in the list.";
ot->idname= "BOID_OT_boidrule_move_down";
ot->exec= boidrule_move_down_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ add/del boid state operators *********************/
static int boidstate_add_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob= ptr.id.data;
ParticleSettings *part;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
part = psys->part;
for(state=part->boids->states.first; state; state=state->next)
state->flag &= ~BOIDSTATE_CURRENT;
state = boid_new_state(part->boids);
state->flag |= BOIDSTATE_CURRENT;
BLI_addtail(&part->boids->states, state);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void BOID_OT_boidstate_add(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Add Boid State";
ot->description = "Add a boid state to the particle system.";
ot->idname= "BOID_OT_boidstate_add";
/* api callbacks */
ot->exec= boidstate_add_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int boidstate_del_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
ParticleSettings *part;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
part = psys->part;
for(state=part->boids->states.first; state; state=state->next) {
if(state->flag & BOIDSTATE_CURRENT) {
BLI_remlink(&part->boids->states, state);
MEM_freeN(state);
break;
}
}
/* there must be at least one state */
if(!part->boids->states.first) {
state = boid_new_state(part->boids);
BLI_addtail(&part->boids->states, state);
}
else
state = part->boids->states.first;
state->flag |= BOIDSTATE_CURRENT;
DAG_scene_sort(scene);
psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
void BOID_OT_boidstate_del(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Remove Boid State";
ot->idname= "BOID_OT_boidstate_del";
/* api callbacks */
ot->exec= boidstate_del_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ move up/down boid state operators *********************/
static int boidstate_move_up_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
BoidSettings *boids;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
boids = psys->part->boids;
for(state = boids->states.first; state; state=state->next) {
if(state->flag & BOIDSTATE_CURRENT && state->prev) {
BLI_remlink(&boids->states, state);
BLI_insertlink(&boids->states, state->prev->prev, state);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
break;
}
}
return OPERATOR_FINISHED;
}
void BOID_OT_boidstate_move_up(wmOperatorType *ot)
{
ot->name= "Move Up Boid State";
ot->description= "Move boid state up in the list.";
ot->idname= "BOID_OT_boidstate_move_up";
ot->exec= boidstate_move_up_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int boidstate_move_down_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
BoidSettings *boids;
BoidState *state;
if(!psys || !psys->part || psys->part->phystype != PART_PHYS_BOIDS)
return OPERATOR_CANCELLED;
boids = psys->part->boids;
for(state = boids->states.first; state; state=state->next) {
if(state->flag & BOIDSTATE_CURRENT && state->next) {
BLI_remlink(&boids->states, state);
BLI_insertlink(&boids->states, state->next, state);
psys_flush_particle_settings(scene, psys->part, PSYS_RECALC_RESET);
break;
}
}
return OPERATOR_FINISHED;
}
void BOID_OT_boidstate_move_down(wmOperatorType *ot)
{
ot->name= "Move Down Boid State";
ot->description= "Move boid state down in the list.";
ot->idname= "BOID_OT_boidstate_move_down";
ot->exec= boidstate_move_down_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/*******************************************************************************/
void ED_operatortypes_boids(void)
{
WM_operatortype_append(BOID_OT_boidrule_add);
WM_operatortype_append(BOID_OT_boidrule_del);
WM_operatortype_append(BOID_OT_boidrule_move_up);
WM_operatortype_append(BOID_OT_boidrule_move_down);
WM_operatortype_append(BOID_OT_boidstate_add);
WM_operatortype_append(BOID_OT_boidstate_del);
WM_operatortype_append(BOID_OT_boidstate_move_up);
WM_operatortype_append(BOID_OT_boidstate_move_down);
}

View File

@@ -93,6 +93,7 @@ void ED_spacetypes_init(void)
ED_operatortypes_marker();
ED_operatortypes_pointcache();
ED_operatortypes_fluid();
ED_operatortypes_boids();
ui_view2d_operatortypes();

View File

@@ -78,10 +78,10 @@ void OBJECT_OT_particle_system_add(struct wmOperatorType *ot);
void OBJECT_OT_particle_system_remove(struct wmOperatorType *ot);
void PARTICLE_OT_new(struct wmOperatorType *ot);
void PARTICLE_OT_new_keyed_target(struct wmOperatorType *ot);
void PARTICLE_OT_remove_keyed_target(struct wmOperatorType *ot);
void PARTICLE_OT_keyed_target_move_up(struct wmOperatorType *ot);
void PARTICLE_OT_keyed_target_move_down(struct wmOperatorType *ot);
void PARTICLE_OT_new_target(struct wmOperatorType *ot);
void PARTICLE_OT_remove_target(struct wmOperatorType *ot);
void PARTICLE_OT_target_move_up(struct wmOperatorType *ot);
void PARTICLE_OT_target_move_down(struct wmOperatorType *ot);
void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);

View File

@@ -30,6 +30,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_boid_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_object_types.h"
@@ -57,6 +58,7 @@
#include "BLI_listbase.h"
#include "RNA_access.h"
#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -623,7 +625,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *op)
if(psys->part)
part= psys_copy_settings(psys->part);
else
part= psys_new_settings("PSys", bmain);
part= psys_new_settings("ParticleSettings", bmain);
ob= ptr.id.data;
@@ -632,6 +634,8 @@ static int new_particle_settings_exec(bContext *C, wmOperator *op)
psys->part = part;
psys_check_boid_data(psys);
DAG_scene_sort(scene);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
@@ -655,28 +659,28 @@ void PARTICLE_OT_new(wmOperatorType *ot)
/********************** keyed particle target operators *********************/
static int new_keyed_particle_target_exec(bContext *C, wmOperator *op)
static int new_particle_target_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
KeyedParticleTarget *kpt;
ParticleTarget *pt;
if(!psys)
return OPERATOR_CANCELLED;
kpt = psys->keyed_targets.first;
for(; kpt; kpt=kpt->next)
kpt->flag &= ~KEYED_TARGET_CURRENT;
pt = psys->targets.first;
for(; pt; pt=pt->next)
pt->flag &= ~PTARGET_CURRENT;
kpt = MEM_callocN(sizeof(KeyedParticleTarget), "keyed particle target");
pt = MEM_callocN(sizeof(ParticleTarget), "keyed particle target");
kpt->flag |= KEYED_TARGET_CURRENT;
kpt->psys = 1;
pt->flag |= PTARGET_CURRENT;
pt->psys = 1;
BLI_addtail(&psys->keyed_targets, kpt);
BLI_addtail(&psys->targets, pt);
DAG_scene_sort(scene);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
@@ -686,44 +690,44 @@ static int new_keyed_particle_target_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void PARTICLE_OT_new_keyed_target(wmOperatorType *ot)
void PARTICLE_OT_new_target(wmOperatorType *ot)
{
/* identifiers */
ot->name= "New Keyed Particle Target";
ot->idname= "PARTICLE_OT_new_keyed_target";
ot->name= "New Particle Target";
ot->idname= "PARTICLE_OT_new_target";
/* api callbacks */
ot->exec= new_keyed_particle_target_exec;
ot->exec= new_particle_target_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int remove_keyed_particle_target_exec(bContext *C, wmOperator *op)
static int remove_particle_target_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
KeyedParticleTarget *kpt;
ParticleTarget *pt;
if(!psys)
return OPERATOR_CANCELLED;
kpt = psys->keyed_targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->flag & KEYED_TARGET_CURRENT) {
BLI_remlink(&psys->keyed_targets, kpt);
MEM_freeN(kpt);
pt = psys->targets.first;
for(; pt; pt=pt->next) {
if(pt->flag & PTARGET_CURRENT) {
BLI_remlink(&psys->targets, pt);
MEM_freeN(pt);
break;
}
}
kpt = psys->keyed_targets.last;
pt = psys->targets.last;
if(kpt)
kpt->flag |= KEYED_TARGET_CURRENT;
if(pt)
pt->flag |= PTARGET_CURRENT;
DAG_scene_sort(scene);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
@@ -733,37 +737,37 @@ static int remove_keyed_particle_target_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void PARTICLE_OT_remove_keyed_target(wmOperatorType *ot)
void PARTICLE_OT_remove_target(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Remove Keyed Particle Target";
ot->idname= "PARTICLE_OT_remove_keyed_target";
ot->name= "Remove Particle Target";
ot->idname= "PARTICLE_OT_remove_target";
/* api callbacks */
ot->exec= remove_keyed_particle_target_exec;
ot->exec= remove_particle_target_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ move up modifier operator *********************/
/************************ move up particle target operator *********************/
static int keyed_target_move_up_exec(bContext *C, wmOperator *op)
static int target_move_up_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
KeyedParticleTarget *kpt;
ParticleTarget *pt;
if(!psys)
return OPERATOR_CANCELLED;
kpt = psys->keyed_targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->flag & KEYED_TARGET_CURRENT && kpt->prev) {
BLI_remlink(&psys->keyed_targets, kpt);
BLI_insertlink(&psys->keyed_targets, kpt->prev->prev, kpt);
pt = psys->targets.first;
for(; pt; pt=pt->next) {
if(pt->flag & PTARGET_CURRENT && pt->prev) {
BLI_remlink(&psys->targets, pt);
BLI_insertlink(&psys->targets, pt->prev->prev, pt);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
@@ -774,35 +778,35 @@ static int keyed_target_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void PARTICLE_OT_keyed_target_move_up(wmOperatorType *ot)
void PARTICLE_OT_target_move_up(wmOperatorType *ot)
{
ot->name= "Move Up Keyed Target";
ot->description= "Move keyed particle target up in the list.";
ot->idname= "PARTICLE_OT_keyed_target_move_up";
ot->name= "Move Up Target";
ot->description= "Move particle target up in the list.";
ot->idname= "PARTICLE_OT_target_move_up";
ot->exec= keyed_target_move_up_exec;
ot->exec= target_move_up_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/************************ move down modifier operator *********************/
/************************ move down particle target operator *********************/
static int keyed_target_move_down_exec(bContext *C, wmOperator *op)
static int target_move_down_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys= ptr.data;
Object *ob = ptr.id.data;
KeyedParticleTarget *kpt;
ParticleTarget *pt;
if(!psys)
return OPERATOR_CANCELLED;
kpt = psys->keyed_targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->flag & KEYED_TARGET_CURRENT && kpt->next) {
BLI_remlink(&psys->keyed_targets, kpt);
BLI_insertlink(&psys->keyed_targets, kpt->next, kpt);
pt = psys->targets.first;
for(; pt; pt=pt->next) {
if(pt->flag & PTARGET_CURRENT && pt->next) {
BLI_remlink(&psys->targets, pt);
BLI_insertlink(&psys->targets, pt->next, pt);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
@@ -813,13 +817,13 @@ static int keyed_target_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
void PARTICLE_OT_keyed_target_move_down(wmOperatorType *ot)
void PARTICLE_OT_target_move_down(wmOperatorType *ot)
{
ot->name= "Move Down Keyed Target";
ot->description= "Move keyed particle target down in the list.";
ot->idname= "PARTICLE_OT_keyed_target_move_down";
ot->name= "Move Down Target";
ot->description= "Move particle target down in the list.";
ot->idname= "PARTICLE_OT_target_move_down";
ot->exec= keyed_target_move_down_exec;
ot->exec= target_move_down_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;

View File

@@ -198,10 +198,10 @@ void buttons_operatortypes(void)
WM_operatortype_append(OBJECT_OT_particle_system_remove);
WM_operatortype_append(PARTICLE_OT_new);
WM_operatortype_append(PARTICLE_OT_new_keyed_target);
WM_operatortype_append(PARTICLE_OT_remove_keyed_target);
WM_operatortype_append(PARTICLE_OT_keyed_target_move_up);
WM_operatortype_append(PARTICLE_OT_keyed_target_move_down);
WM_operatortype_append(PARTICLE_OT_new_target);
WM_operatortype_append(PARTICLE_OT_remove_target);
WM_operatortype_append(PARTICLE_OT_target_move_up);
WM_operatortype_append(PARTICLE_OT_target_move_down);
WM_operatortype_append(SCENE_OT_render_layer_add);
WM_operatortype_append(SCENE_OT_render_layer_remove);

View File

@@ -40,6 +40,7 @@
#include "MTC_matrixops.h"
#include "DNA_armature_types.h"
#include "DNA_boid_types.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_constraint_types.h" // for drawing constraint
@@ -3136,7 +3137,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
Material *ma;
float vel[3], imat[4][4];
float timestep, pixsize=1.0, pa_size, r_tilt, r_length;
float pa_time, pa_birthtime, pa_dietime;
float pa_time, pa_birthtime, pa_dietime, pa_health;
float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
int a, totpart, totpoint=0, totve=0, drawn, draw_as, totchild=0;
@@ -3362,6 +3363,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_birthtime=pa->time;
pa_dietime = pa->dietime;
pa_size=pa->size;
if(part->phystype==PART_PHYS_BOIDS)
pa_health = pa->boid->health;
else
pa_health = -1.0;
#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0){
@@ -3424,6 +3429,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_size=psys_get_child_size(psys,cpa,cfra,0);
pa_health = -1.0;
r_tilt = 2.0f * cpa->rand[2];
r_length = cpa->rand[1];
}
@@ -3506,9 +3513,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
setlinestyle(0);
}
if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
if((part->draw&PART_DRAW_NUM || part->draw&PART_DRAW_HEALTH) && !(G.f & G_RENDER_SHADOW)){
strcpy(val, "");
if(part->draw&PART_DRAW_NUM)
sprintf(val, " %i", a);
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 */
sprintf(val," %i",a);
view3d_particle_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0);
}
}

View File

@@ -427,9 +427,14 @@ typedef struct CollisionModifierData {
typedef struct SurfaceModifierData {
ModifierData modifier;
struct MVert *x; /* old position */
struct MVert *v; /* velocity */
struct DerivedMesh *dm;
struct BVHTreeFromMesh *bvhtree; /* bounding volume hierarchy of the mesh faces */
int cfra, numverts;
} SurfaceModifierData;
typedef enum {

View File

@@ -227,6 +227,7 @@ typedef struct SoftBody {
#define PFIELD_HARMONIC 7
#define PFIELD_CHARGE 8
#define PFIELD_LENNARDJ 9
#define PFIELD_BOID 10
/* pd->flag: various settings */

View File

@@ -61,13 +61,13 @@ typedef struct ChildParticle {
float rand[3];
} ChildParticle;
typedef struct KeyedParticleTarget {
struct KeyedParticleTarget *next, *prev;
typedef struct ParticleTarget {
struct ParticleTarget *next, *prev;
struct Object *ob;
int psys;
short flag, rt;
short flag, mode;
float time, duration;
} KeyedParticleTarget;
} ParticleTarget;
/* Everything that's non dynamic for a particle: */
typedef struct ParticleData {
@@ -82,7 +82,9 @@ typedef struct ParticleData {
ParticleKey *keys; /* keyed states */
float i_rot[4],r_rot[4];/* initial & random values (i_rot should be removed as it's not used anymore)*/
struct BoidData *boid; /* boids data */
float r_rot[4]; /* random values */
float r_ave[3],r_ve[3];
float fuv[4], foffset; /* coordinates on face/edge number "num" and depth along*/
@@ -91,13 +93,10 @@ typedef struct ParticleData {
float time, lifetime; /* dietime is not nescessarily time+lifetime as */
float dietime; /* particles can die unnaturally (collision) */
float bank; /* banking angle for boids */
float size, sizemul; /* size and multiplier so that we can update size when ever */
int num; /* index to vert/edge/face */
int num_dmcache; /* index to derived mesh data (face) to avoid slow lookups */
int pad;
int totkey;
int bpi; /* softbody body point start index */
@@ -112,12 +111,14 @@ typedef struct ParticleSettings {
ID id;
struct AnimData *adt;
struct BoidSettings *boids;
int flag;
short type, from, distr;
/* physics modes */
short phystype, rotmode, avemode, reactevent;
short draw, draw_as, draw_size, childtype;
short ren_as, rt2[3];
short ren_as, rt2;
/* number of path segments, power of 2 except */
short draw_step, ren_step;
short hair_step, keys_step;
@@ -126,7 +127,7 @@ typedef struct ParticleSettings {
short adapt_angle, adapt_pix;
short disp, omat, interpolation, rotfrom, integrator;
short kink, kink_axis, nbetween, boidneighbours;
short kink, kink_axis;
/* billboards */
short bb_align, bb_uv_split, bb_anim, bb_split_offset;
@@ -154,7 +155,7 @@ typedef struct ParticleSettings {
/* children */
int child_nbr, ren_child_nbr;
float parents, childsize, childrandsize;
float childrad, childflat, rt;
float childrad, childflat;
/* clumping */
float clumpfac, clumppow;
/* kink */
@@ -174,11 +175,7 @@ typedef struct ParticleSettings {
/* keyed particles */
int keyed_loops;
/* boids */
float max_vel, max_lat_acc, max_tan_acc;
float average_vel, banking, max_bank, groundz;
float boidfac[8];
char boidrule[8];
float effector_weight[10];
struct Group *dup_group;
struct Group *eff_group;
@@ -212,12 +209,14 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
struct ListBase effectors, reactevents; /* runtime */
struct ListBase keyed_targets;
struct ListBase targets; /* used for keyed and boid physics */
char name[32]; /* particle system name */
float imat[4][4]; /* used for duplicators */
float cfra;
float cfra, tree_frame;
int seed;
int flag, totpart, totchild, totcached, totchildcache, rt;
int flag, totpart, totchild, totcached, totchildcache;
short recalc, target_psys, totkeyed, softflag, bakespace, rt2;
char bb_uvname[3][32]; /* billboard uv name */
@@ -230,6 +229,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
/* point cache */
struct PointCache *pointcache;
struct KDTree *tree; /* used for interactions with self and other systems */
}ParticleSystem;
/* general particle maximums */
@@ -325,7 +326,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
//#define PART_DRAW_PATH_LEN 2
#define PART_DRAW_SIZE 4
#define PART_DRAW_EMITTER 8 /* render emitter also */
//#define PART_DRAW_HEALTH 16
#define PART_DRAW_HEALTH 16
#define PART_ABS_PATH_TIME 32
//#define PART_DRAW_TRAIL 64
#define PART_DRAW_BB_LOCK 128
@@ -460,26 +461,13 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define PSYS_VG_ROT 10
#define PSYS_VG_EFFECTOR 11
/* part->boidrules */
#define BOID_TOT_RULES 8
/* ParticleTarget->flag */
#define PTARGET_CURRENT 1
#define PTARGET_VALID 2
#define BOID_COLLIDE 0
#define BOID_AVOID 1
#define BOID_CROWD 2
#define BOID_CENTER 3
#define BOID_AV_VEL 4
#define BOID_VEL_MATCH 5
#define BOID_GOAL 6
#define BOID_LEVEL 7
/* psys->keyed_targets->flag */
#define KEYED_TARGET_CURRENT 1
#define KEYED_TARGET_VALID 2
//#define PSYS_INTER_CUBIC 0
//#define PSYS_INTER_LINEAR 1
//#define PSYS_INTER_CARDINAL 2
//#define PSYS_INTER_BSPLINE 3
/* ParticleTarget->mode */
#define PTARGET_MODE_NEUTRAL 0
#define PTARGET_MODE_FRIEND 1
#define PTARGET_MODE_ENEMY 2
#endif

View File

@@ -132,6 +132,7 @@ char *includefiles[] = {
// of makesdna.c (this file) as well
"DNA_windowmanager_types.h",
"DNA_anim_types.h",
"DNA_boid_types.h",
// empty string to indicate end of includefiles
""
@@ -1154,4 +1155,5 @@ int main(int argc, char ** argv)
#include "DNA_gpencil_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_anim_types.h"
#include "DNA_boid_types.h"
/* end of list */

View File

@@ -221,7 +221,7 @@ extern StructRNA RNA_Key;
extern StructRNA RNA_KeyboardSensor;
extern StructRNA RNA_KeyingSet;
extern StructRNA RNA_KeyingSetPath;
extern StructRNA RNA_KeyedParticleTarget;
extern StructRNA RNA_ParticleTarget;
extern StructRNA RNA_KinematicConstraint;
extern StructRNA RNA_Lamp;
extern StructRNA RNA_LampSkySettings;

View File

@@ -34,6 +34,7 @@ extern EnumPropertyItem space_type_items[];
extern EnumPropertyItem region_type_items[];
extern EnumPropertyItem modifier_type_items[];
extern EnumPropertyItem constraint_type_items[];
extern EnumPropertyItem boidrule_type_items[];
extern EnumPropertyItem beztriple_handle_type_items[];
extern EnumPropertyItem beztriple_interpolation_mode_items[];

View File

@@ -1901,6 +1901,7 @@ RNAProcessItem PROCESS_ITEMS[]= {
{"rna_animation.c", NULL, RNA_def_animation},
{"rna_actuator.c", NULL, RNA_def_actuator},
{"rna_armature.c", NULL, RNA_def_armature},
{"rna_boid.c", NULL, RNA_def_boid},
{"rna_brush.c", NULL, RNA_def_brush},
{"rna_camera.c", NULL, RNA_def_camera},
{"rna_cloth.c", NULL, RNA_def_cloth},

View File

@@ -0,0 +1,615 @@
/**
* $Id: rna_modifier.c 21514 2009-07-11 05:41:21Z aligorith $
*
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2009 by Janne Karhu.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <float.h>
#include <limits.h>
#include <stdlib.h>
#include "RNA_define.h"
#include "RNA_types.h"
#include "rna_internal.h"
#include "DNA_scene_types.h"
#include "DNA_boid_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "WM_types.h"
EnumPropertyItem boidrule_type_items[] ={
{eBoidRuleType_Goal, "GOAL", 0, "Goal", "Go to assigned object or loudest assigned signal source."},
{eBoidRuleType_Avoid, "AVOID", 0, "Avoid", "Get away from assigned object or loudest assigned signal source."},
{eBoidRuleType_AvoidCollision, "AVOID_COLLISION", 0, "Avoid Collision", "Monoeuver to avoid collisions with other boids and deflector objects in near future."},
{eBoidRuleType_Separate, "SEPARATE", 0, "Separate", "Keep from going through other boids."},
{eBoidRuleType_Flock, "FLOCK", 0, "Flock", "Move to center of neighbors and match their velocity."},
{eBoidRuleType_FollowLeader, "FOLLOW_LEADER", 0, "Follow Leader", "Follow a boid or assigned object."},
{eBoidRuleType_AverageSpeed, "AVERAGE_SPEED", 0, "Average Speed", "Maintain speed, flight level or wander."},
{eBoidRuleType_Fight, "FIGHT", 0, "Fight", "Go to closest enemy and attack when in range."},
//{eBoidRuleType_Protect, "PROTECT", 0, "Protect", "Go to enemy closest to target and attack when in range."},
//{eBoidRuleType_Hide, "HIDE", 0, "Hide", "Find a deflector move to it's other side from closest enemy."},
//{eBoidRuleType_FollowPath, "FOLLOW_PATH", 0, "Follow Path", "Move along a assigned curve or closest curve in a group."},
//{eBoidRuleType_FollowWall, "FOLLOW_WALL", 0, "Follow Wall", "Move next to a deflector object's in direction of it's tangent."},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem boidruleset_type_items[] ={
{eBoidRulesetType_Fuzzy, "FUZZY", 0, "Fuzzy", "Rules are gone through top to bottom. Only the first rule that effect above fuzziness threshold is evaluated."},
{eBoidRulesetType_Random, "RANDOM", 0, "Random", "A random rule is selected for each boid."},
{eBoidRulesetType_Average, "AVERAGE", 0, "Average", "All rules are averaged."},
{0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_particle.h"
static void rna_Boids_reset(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
if(ptr->type==&RNA_ParticleSystem) {
ParticleSystem *psys = (ParticleSystem*)ptr->data;
Object *ob = psys_find_object(scene, psys);
psys->recalc = PSYS_RECALC_RESET;
if(ob) {
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
}
else {
part = ptr->id.data;
psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
}
}
static void rna_Boids_reset_deps(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
ParticleSettings *part;
if(ptr->type==&RNA_ParticleSystem) {
ParticleSystem *psys = (ParticleSystem*)ptr->data;
Object *ob = psys_find_object(scene, psys);
psys->recalc = PSYS_RECALC_RESET;
if(ob) {
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
}
else {
part = ptr->id.data;
psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET);
DAG_scene_sort(scene);
}
}
static StructRNA* rna_BoidRule_refine(struct PointerRNA *ptr)
{
BoidRule *rule= (BoidRule*)ptr->data;
switch(rule->type) {
case eBoidRuleType_Goal:
return &RNA_BoidRuleGoal;
case eBoidRuleType_Avoid:
return &RNA_BoidRuleAvoid;
case eBoidRuleType_AvoidCollision:
return &RNA_BoidRuleAvoidCollision;
case eBoidRuleType_FollowLeader:
return &RNA_BoidRuleFollowLeader;
case eBoidRuleType_AverageSpeed:
return &RNA_BoidRuleAverageSpeed;
case eBoidRuleType_Fight:
return &RNA_BoidRuleFight;
default:
return &RNA_BoidRule;
}
}
static char *rna_BoidRule_path(PointerRNA *ptr)
{
return BLI_sprintfN("rules[%s]", ((BoidRule*)ptr->data)->name); // XXX not unique
}
static PointerRNA rna_BoidState_active_boid_rule_get(PointerRNA *ptr)
{
BoidState *state= (BoidState*)ptr->data;
BoidRule *rule = (BoidRule*)state->rules.first;
for(; rule; rule=rule->next) {
if(rule->flag & BOIDRULE_CURRENT)
return rna_pointer_inherit_refine(ptr, &RNA_BoidRule, rule);
}
return rna_pointer_inherit_refine(ptr, &RNA_BoidRule, NULL);
}
static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min, int *max)
{
BoidState *state= (BoidState*)ptr->data;
*min= 0;
*max= BLI_countlist(&state->rules)-1;
*max= MAX2(0, *max);
}
static int rna_BoidState_active_boid_rule_index_get(PointerRNA *ptr)
{
BoidState *state= (BoidState*)ptr->data;
BoidRule *rule = (BoidRule*)state->rules.first;
int i=0;
for(; rule; rule=rule->next, i++) {
if(rule->flag & BOIDRULE_CURRENT)
return i;
}
return 0;
}
static void rna_BoidState_active_boid_rule_index_set(struct PointerRNA *ptr, int value)
{
BoidState *state= (BoidState*)ptr->data;
BoidRule *rule = (BoidRule*)state->rules.first;
int i=0;
for(; rule; rule=rule->next, i++) {
if(i==value)
rule->flag |= BOIDRULE_CURRENT;
else
rule->flag &= ~BOIDRULE_CURRENT;
}
}
static PointerRNA rna_BoidSettings_active_boid_state_get(PointerRNA *ptr)
{
BoidSettings *boids= (BoidSettings*)ptr->data;
BoidState *state = (BoidState*)boids->states.first;
for(; state; state=state->next) {
if(state->flag & BOIDSTATE_CURRENT)
return rna_pointer_inherit_refine(ptr, &RNA_BoidState, state);
}
return rna_pointer_inherit_refine(ptr, &RNA_BoidState, NULL);
}
static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int *min, int *max)
{
BoidSettings *boids= (BoidSettings*)ptr->data;
*min= 0;
*max= BLI_countlist(&boids->states)-1;
*max= MAX2(0, *max);
}
static int rna_BoidSettings_active_boid_state_index_get(PointerRNA *ptr)
{
BoidSettings *boids= (BoidSettings*)ptr->data;
BoidState *state = (BoidState*)boids->states.first;
int i=0;
for(; state; state=state->next, i++) {
if(state->flag & BOIDSTATE_CURRENT)
return i;
}
return 0;
}
static void rna_BoidSettings_active_boid_state_index_set(struct PointerRNA *ptr, int value)
{
BoidSettings *boids= (BoidSettings*)ptr->data;
BoidState *state = (BoidState*)boids->states.first;
int i=0;
for(; state; state=state->next, i++) {
if(i==value)
state->flag |= BOIDSTATE_CURRENT;
else
state->flag &= ~BOIDSTATE_CURRENT;
}
}
#else
static void rna_def_boidrule_goal(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleGoal", "BoidRule");
RNA_def_struct_ui_text(srna, "Goal", "");
RNA_def_struct_sdna(srna, "BoidRuleGoalAvoid");
prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Goal object.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset_deps");
prop= RNA_def_property(srna, "predict", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_GOAL_AVOID_PREDICT);
RNA_def_property_ui_text(prop, "Predict", "Predict target movement.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule_avoid(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleAvoid", "BoidRule");
RNA_def_struct_ui_text(srna, "Avoid", "");
RNA_def_struct_sdna(srna, "BoidRuleGoalAvoid");
prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Object to avoid.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset_deps");
prop= RNA_def_property(srna, "predict", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_GOAL_AVOID_PREDICT);
RNA_def_property_ui_text(prop, "Predict", "Predict target movement.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "fear_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Fear factor", "Avoid object if danger from it is above this threshol.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule_avoid_collision(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleAvoidCollision", "BoidRule");
RNA_def_struct_ui_text(srna, "Avoid Collision", "");
prop= RNA_def_property(srna, "boids", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_ACOLL_WITH_BOIDS);
RNA_def_property_ui_text(prop, "Boids", "Avoid collision with other boids.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "deflectors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_ACOLL_WITH_DEFLECTORS);
RNA_def_property_ui_text(prop, "Deflectors", "Avoid collision with deflector objects.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "look_ahead", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Look ahead", "Time to look ahead in seconds.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule_follow_leader(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleFollowLeader", "BoidRule");
RNA_def_struct_ui_text(srna, "Follow Leader", "");
prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Object", "Follow this object instead of a boid.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset_deps");
prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Distance", "Distance behind leader to follow.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "queue_size", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Queue Size", "How many boids in a line.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "line", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BRULE_LEADER_IN_LINE);
RNA_def_property_ui_text(prop, "Line", "Follow leader in a line.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule_average_speed(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleAverageSpeed", "BoidRule");
RNA_def_struct_ui_text(srna, "Average Speed", "");
prop= RNA_def_property(srna, "wander", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Wander", "How fast velocity's direction is randomized.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "level", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Level", "How much velocity's z-component is kept constant.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Speed", "Percentage of maximum speed.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule_fight(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "BoidRuleFight", "BoidRule");
RNA_def_struct_ui_text(srna, "Fight", "");
prop= RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Fight Distance", "Attack boids at max this distance.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "flee_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 100.0f);
RNA_def_property_ui_text(prop, "Flee Distance", "Flee to this distance.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boidrule(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
/* data */
srna= RNA_def_struct(brna, "BoidRule", NULL);
RNA_def_struct_ui_text(srna , "Boid Rule", "");
RNA_def_struct_refine_func(srna, "rna_BoidRule_refine");
RNA_def_struct_path_func(srna, "rna_BoidRule_path");
/* strings */
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Boid rule name.");
RNA_def_struct_name_property(srna, prop);
/* enums */
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, boidrule_type_items);
RNA_def_property_ui_text(prop, "Type", "");
/* flags */
prop= RNA_def_property(srna, "in_air", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_IN_AIR);
RNA_def_property_ui_text(prop, "In Air", "Use rule when boid is flying.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "on_land", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BOIDRULE_ON_LAND);
RNA_def_property_ui_text(prop, "On Land", "Use rule when boid is on land.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
//prop= RNA_def_property(srna, "expanded", PROP_BOOLEAN, PROP_NONE);
//RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded);
//RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface.");
/* types */
rna_def_boidrule_goal(brna);
rna_def_boidrule_avoid(brna);
rna_def_boidrule_avoid_collision(brna);
rna_def_boidrule_follow_leader(brna);
rna_def_boidrule_average_speed(brna);
rna_def_boidrule_fight(brna);
}
static void rna_def_boidstate(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BoidState", NULL);
RNA_def_struct_ui_text(srna, "Boid State", "Boid state for boid physics.");
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Boid state name.");
RNA_def_struct_name_property(srna, prop);
prop= RNA_def_property(srna, "ruleset_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, boidruleset_type_items);
RNA_def_property_ui_text(prop, "Rule Evaluation", "How the rules in the list are evaluated.");
prop= RNA_def_property(srna, "rules", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidRule");
RNA_def_property_ui_text(prop, "Boid Rules", "");
prop= RNA_def_property(srna, "active_boid_rule", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidRule");
RNA_def_property_pointer_funcs(prop, "rna_BoidState_active_boid_rule_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Boid Rule", "");
prop= RNA_def_property(srna, "active_boid_rule_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_BoidState_active_boid_rule_index_get", "rna_BoidState_active_boid_rule_index_set", "rna_BoidState_active_boid_rule_index_range");
RNA_def_property_ui_text(prop, "Active Boid Rule Index", "");
prop= RNA_def_property(srna, "rule_fuzziness", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Rule Fuzzines", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Volume", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(prop, "Falloff", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
static void rna_def_boid_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BoidSettings", NULL);
RNA_def_struct_ui_text(srna, "Boid Settings", "Settings for boid physics.");
prop= RNA_def_property(srna, "landing_smoothness", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(prop, "Landing Smoothness", "How smoothly the boids land.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "banking", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 2.0);
RNA_def_property_ui_text(prop, "Banking", "Amount of rotation around velocity vector on turns.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 2.0);
RNA_def_property_ui_text(prop, "Height", "Boid height relative to particle size.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
/* states */
prop= RNA_def_property(srna, "states", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidState");
RNA_def_property_ui_text(prop, "Boid States", "");
prop= RNA_def_property(srna, "active_boid_state", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidRule");
RNA_def_property_pointer_funcs(prop, "rna_BoidSettings_active_boid_state_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Boid Rule", "");
prop= RNA_def_property(srna, "active_boid_state_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_BoidSettings_active_boid_state_index_get", "rna_BoidSettings_active_boid_state_index_set", "rna_BoidSettings_active_boid_state_index_range");
RNA_def_property_ui_text(prop, "Active Boid State Index", "");
/* character properties */
prop= RNA_def_property(srna, "health", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Health", "Initial boid health when born.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Strength", "Maximum caused damage on attack per second.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "aggression", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Aggression", "Boid will fight this times stronger enemy.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "accuracy", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Accuracy", "Accuracy of attack.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "range", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Range", "The maximum distance from which a boid can attack.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
/* physical properties */
prop= RNA_def_property(srna, "air_min_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Min Air Speed", "Minimum speed in air (relative to maximum speed).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "air_max_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Max Air Speed", "Maximum speed in air.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "air_max_acc", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Max Air Acceleration", "Maximum acceleration in air (relative to maximum speed).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "air_max_ave", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Max Air Angular Velocity", "Maximum angular velocity in air (relative to 180 degrees).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "air_personal_space", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(prop, "Air Personal Space", "Radius of boids personal space in air (% of particle size).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_jump_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Jump Speed", "Maximum speed for jumping.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_max_speed", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_text(prop, "Max Land Speed", "Maximum speed on land.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_max_acc", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Max Land Acceleration", "Maximum acceleration on land (relative to maximum speed).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_max_ave", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Max Land Angular Velocity", "Maximum angular velocity on land (relative to 180 degrees).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_personal_space", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 10.0);
RNA_def_property_ui_text(prop, "Land Personal Space", "Radius of boids personal space on land (% of particle size).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "land_stick_force", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1000.0);
RNA_def_property_ui_text(prop, "Land Stick Force", "How strong a force must be to start effecting a boid on land.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
/* options */
prop= RNA_def_property(srna, "allow_flight", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_FLIGHT);
RNA_def_property_ui_text(prop, "Allow Flight", "Allow boids to move in air.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "allow_land", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_LAND);
RNA_def_property_ui_text(prop, "Allow Land", "Allow boids to move on land.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
prop= RNA_def_property(srna, "allow_climb", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "options", BOID_ALLOW_CLIMB);
RNA_def_property_ui_text(prop, "Allow Climbing", "Allow boids to climb goal objects.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Boids_reset");
}
void RNA_def_boid(BlenderRNA *brna)
{
rna_def_boidrule(brna);
rna_def_boidstate(brna);
rna_def_boid_settings(brna);
}
#endif

View File

@@ -93,7 +93,7 @@ static void rna_FluidSettings_update_type(bContext *C, PointerRNA *ptr)
if(ob->type == OB_MESH && !psys) {
/* add particle system */
part= psys_new_settings("PSys", bmain);
part= psys_new_settings("ParticleSettings", bmain);
psys= MEM_callocN(sizeof(ParticleSystem), "particle_system");
part->type= PART_FLUID;

View File

@@ -117,6 +117,7 @@ void RNA_def_action(struct BlenderRNA *brna);
void RNA_def_animation(struct BlenderRNA *brna);
void RNA_def_armature(struct BlenderRNA *brna);
void RNA_def_actuator(struct BlenderRNA *brna);
void RNA_def_boid(struct BlenderRNA *brna);
void RNA_def_brush(struct BlenderRNA *brna);
void RNA_def_brushclone(struct BlenderRNA *brna);
void RNA_def_camera(struct BlenderRNA *brna);

View File

@@ -284,7 +284,7 @@ static void rna_FieldSettings_surface_update(bContext *C, PointerRNA *ptr)
/* add/remove modifier as needed */
if(!md) {
if(pd && (pd->flag & PFIELD_SURFACE))
if(ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ))
if(ELEM6(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ,PFIELD_BOID))
if(ELEM4(ob->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE))
ED_object_modifier_add(NULL, scene, ob, eModifierType_Surface);
}
@@ -504,6 +504,7 @@ static void rna_def_field(BlenderRNA *brna)
{PFIELD_HARMONIC, "HARMONIC", 0, "Harmonic", ""},
{PFIELD_CHARGE, "CHARGE", 0, "Charge", ""},
{PFIELD_LENNARDJ, "LENNARDJ", 0, "Lennard-Jones", ""},
{PFIELD_BOID, "BOID", 0, "Boid", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem falloff_items[] = {

View File

@@ -29,6 +29,7 @@
#include "RNA_define.h"
#include "RNA_types.h"
#include "RNA_access.h"
#include "rna_internal.h"
@@ -36,6 +37,7 @@
#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_boid_types.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -140,13 +142,33 @@ static void rna_Particle_reset(bContext *C, PointerRNA *ptr)
}
}
static void rna_Particle_keyed_reset(bContext *C, PointerRNA *ptr)
static void rna_Particle_target_reset(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
if(ptr->type==&RNA_KeyedParticleTarget) {
if(ptr->type==&RNA_ParticleTarget) {
ParticleTarget *pt = (ParticleTarget*)ptr->data;
Object *ob = (Object*)ptr->id.data;
ParticleSystem *psys = psys_get_current(ob);
ParticleSystem *kpsys=NULL, *psys=psys_get_current(ob);
int psys_num = BLI_findindex(&ob->particlesystem, psys);
if(pt->ob==ob || pt->ob==NULL) {
kpsys = BLI_findlink(&ob->particlesystem, pt->psys-1);
if(kpsys)
pt->flag |= PTARGET_VALID;
else
pt->flag &= ~PTARGET_VALID;
}
else {
if(pt->ob)
kpsys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1);
if(kpsys)
pt->flag |= PTARGET_VALID;
else
pt->flag &= ~PTARGET_VALID;
}
psys->recalc = PSYS_RECALC_RESET;
@@ -155,11 +177,11 @@ static void rna_Particle_keyed_reset(bContext *C, PointerRNA *ptr)
}
}
static void rna_Particle_keyed_redo(bContext *C, PointerRNA *ptr)
static void rna_Particle_target_redo(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
if(ptr->type==&RNA_KeyedParticleTarget) {
if(ptr->type==&RNA_ParticleTarget) {
Object *ob = (Object*)ptr->id.data;
ParticleSystem *psys = psys_get_current(ob);
@@ -235,8 +257,10 @@ static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value)
psys->part = (ParticleSettings *)value.data;
if(psys->part)
if(psys->part) {
psys->part->id.us++;
psys_check_boid_data(psys);
}
}
static void rna_Particle_abspathtime_update(bContext *C, PointerRNA *ptr)
{
@@ -315,97 +339,100 @@ static float rna_PartSetting_linelenhead_get(struct PointerRNA *ptr)
return settings->draw_line[1];
}
static int rna_ParticleSystem_name_length(PointerRNA *ptr)
{
ParticleSystem *psys= ptr->data;
if(psys->part)
return strlen(psys->part->id.name+2);
return 0;
}
static void rna_ParticleSystem_name_get(PointerRNA *ptr, char *str)
{
ParticleSystem *psys= ptr->data;
if(psys->part)
strcpy(str, psys->part->id.name+2);
else
strcpy(str, "");
}
static PointerRNA rna_ParticleSystem_active_keyed_target_get(PointerRNA *ptr)
static PointerRNA rna_ParticleSystem_active_particle_target_get(PointerRNA *ptr)
{
ParticleSystem *psys= (ParticleSystem*)ptr->data;
KeyedParticleTarget *kpt = psys->keyed_targets.first;
ParticleTarget *pt = psys->targets.first;
for(; kpt; kpt=kpt->next) {
if(kpt->flag & KEYED_TARGET_CURRENT)
return rna_pointer_inherit_refine(ptr, &RNA_KeyedParticleTarget, kpt);
for(; pt; pt=pt->next) {
if(pt->flag & PTARGET_CURRENT)
return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, pt);
}
return rna_pointer_inherit_refine(ptr, &RNA_KeyedParticleTarget, NULL);
return rna_pointer_inherit_refine(ptr, &RNA_ParticleTarget, NULL);
}
static void rna_ParticleSystem_active_keyed_target_index_range(PointerRNA *ptr, int *min, int *max)
static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *ptr, int *min, int *max)
{
ParticleSystem *psys= (ParticleSystem*)ptr->data;
*min= 0;
*max= BLI_countlist(&psys->keyed_targets)-1;
*max= BLI_countlist(&psys->targets)-1;
*max= MAX2(0, *max);
}
static int rna_ParticleSystem_active_keyed_target_index_get(PointerRNA *ptr)
static int rna_ParticleSystem_active_particle_target_index_get(PointerRNA *ptr)
{
ParticleSystem *psys= (ParticleSystem*)ptr->data;
KeyedParticleTarget *kpt = psys->keyed_targets.first;
ParticleTarget *pt = psys->targets.first;
int i=0;
for(; kpt; kpt=kpt->next, i++)
if(kpt->flag & KEYED_TARGET_CURRENT)
for(; pt; pt=pt->next, i++)
if(pt->flag & PTARGET_CURRENT)
return i;
return 0;
}
static void rna_ParticleSystem_active_keyed_target_index_set(struct PointerRNA *ptr, int value)
static void rna_ParticleSystem_active_particle_target_index_set(struct PointerRNA *ptr, int value)
{
ParticleSystem *psys= (ParticleSystem*)ptr->data;
KeyedParticleTarget *kpt = psys->keyed_targets.first;
ParticleTarget *pt = psys->targets.first;
int i=0;
for(; kpt; kpt=kpt->next, i++) {
for(; pt; pt=pt->next, i++) {
if(i==value)
kpt->flag |= KEYED_TARGET_CURRENT;
pt->flag |= PTARGET_CURRENT;
else
kpt->flag &= ~KEYED_TARGET_CURRENT;
pt->flag &= ~PTARGET_CURRENT;
}
}
static int rna_KeyedParticleTarget_name_length(PointerRNA *ptr)
static int rna_ParticleTarget_name_length(PointerRNA *ptr)
{
KeyedParticleTarget *kpt= ptr->data;
ParticleTarget *pt= ptr->data;
if(kpt->flag & KEYED_TARGET_VALID) {
if(kpt->ob)
return strlen(kpt->ob->id.name+2) + 4;
if(pt->flag & PTARGET_VALID) {
ParticleSystem *psys = NULL;
if(pt->ob)
psys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1);
else {
Object *ob = (Object*) ptr->id.data;
psys = BLI_findlink(&ob->particlesystem, pt->psys-1);
}
if(psys) {
if(pt->ob)
return strlen(pt->ob->id.name+2) + 2 + strlen(psys->name);
else
return strlen(psys->name);
}
else
return 20;
return 15;
}
else
return 15;
return 0;
}
static void rna_KeyedParticleTarget_name_get(PointerRNA *ptr, char *str)
static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *str)
{
KeyedParticleTarget *kpt= ptr->data;
ParticleTarget *pt= ptr->data;
if(kpt->flag & KEYED_TARGET_VALID) {
if(kpt->ob)
sprintf(str, "%s: %i", kpt->ob->id.name+2, kpt->psys);
if(pt->flag & PTARGET_VALID) {
ParticleSystem *psys = NULL;
if(pt->ob)
psys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1);
else {
Object *ob = (Object*) ptr->id.data;
psys = BLI_findlink(&ob->particlesystem, pt->psys-1);
}
if(psys) {
if(pt->ob)
sprintf(str, "%s: %s", pt->ob->id.name+2, psys->name);
else
strcpy(str, psys->name);
}
else
sprintf(str, "Particle System: %i", kpt->psys);
strcpy(str, "Invalid target!");
}
else
strcpy(str, "Invalid target!");
@@ -636,10 +663,10 @@ static void rna_def_particle(BlenderRNA *brna)
// RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Die Time", "");
prop= RNA_def_property(srna, "banking_angle", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bank");
// RNA_def_property_range(prop, lowerLimitf, upperLimitf);
RNA_def_property_ui_text(prop, "Banking Angle", "");
// prop= RNA_def_property(srna, "banking_angle", PROP_FLOAT, PROP_NONE);
// RNA_def_property_float_sdna(prop, NULL, "bank");
//// RNA_def_property_range(prop, lowerLimitf, upperLimitf);
// RNA_def_property_ui_text(prop, "Banking Angle", "");
prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
// RNA_def_property_range(prop, lowerLimitf, upperLimitf);
@@ -1024,10 +1051,10 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Emitter", "Render emitter Object also.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
//prop= RNA_def_property(srna, "draw_health", PROP_BOOLEAN, PROP_NONE);
//RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH);
//RNA_def_property_ui_text(prop, "Health", "Draw boid health");
//RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
prop= RNA_def_property(srna, "draw_health", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH);
RNA_def_property_ui_text(prop, "Health", "Draw boid health");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
prop= RNA_def_property(srna, "abs_path_time", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_ABS_PATH_TIME);
@@ -1149,9 +1176,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
//interpolation
//TODO: can't find where interpolation is used
//TODO: is this read only/internal?
prop= RNA_def_property(srna, "rotate_from", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "rotfrom");
@@ -1173,19 +1197,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Axis", "Which axis to use for offset");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
/* used?
prop= RNA_def_property(srna, "inbetween", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "nbetween");
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Inbetween", "");
*/
prop= RNA_def_property(srna, "boid_neighbours", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "boidneighbours");
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Neighbours", "How many neighbours to consider for each boid");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* billboards */
prop= RNA_def_property(srna, "billboard_align", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "bb_align");
@@ -1421,6 +1432,12 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Acceleration", "Constant acceleration");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_NONE);
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, NC_OBJECT|ND_PARTICLE, "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);
@@ -1619,46 +1636,12 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
/* boids */
prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_vel");
RNA_def_property_range(prop, 0.0f, 200.0f);
RNA_def_property_ui_text(prop, "Maximum Velocity", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "boids", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BoidSettings");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Boid Settings", "");
prop= RNA_def_property(srna, "lateral_acceleration_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_lat_acc");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Lateral Acceleration", "Lateral acceleration % of max velocity");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "tangential_acceleration_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_tan_acc");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Tangential acceleration", "Tangential acceleration % of max velocity");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "average_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "average_vel");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Average Velocity", "The usual speed % of max velocity");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "banking", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, -10.0f, 10.0f);
RNA_def_property_ui_text(prop, "Banking", "Banking of boids on turns (1.0==natural banking)");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "banking_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_bank");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Maximum Banking", "How much a boid can bank at a single step");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "ground_z", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "groundz");
RNA_def_property_range(prop, -100.0f, 100.0f);
RNA_def_property_ui_text(prop, "Ground Z", "Default Z value");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* draw objects & groups */
prop= RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
@@ -1667,13 +1650,6 @@ 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, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
prop= RNA_def_property(srna, "effector_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "eff_group");
RNA_def_property_struct_type(prop, "Group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
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");
@@ -1687,6 +1663,74 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Billboard Object", "Billboards face this object (default is active camera)");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
/* effectors */
prop= RNA_def_property(srna, "effector_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "eff_group");
RNA_def_property_struct_type(prop, "Group");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Effector Group", "Limit effectors to this Group.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_all", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[0]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "All", "All effector's weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_spherical", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[1]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Spherical", "Spherical effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_vortex", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[2]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Vortex", "Vortex effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_magnetic", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[3]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Magnetic", "Magnetic effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_wind", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[4]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Wind", "Wind effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_curveguide", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[5]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Curve Guide", "Curve guide effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_texture", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[6]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Magnetic", "Texture effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_harmonic", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[7]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Harmonic", "Harmonic effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_charge", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[8]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Charge", "Charge effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "eweight_lennardjones", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "effector_weight[9]");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Lennard-Jones", "Lennard-Jones effector weight.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* animation here? */
rna_def_animdata_common(srna);
@@ -1695,17 +1739,25 @@ static void rna_def_particle_settings(BlenderRNA *brna)
// struct PartDeflect *pd2;
}
static void rna_def_keyed_particle_target(BlenderRNA *brna)
static void rna_def_particle_target(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "KeyedParticleTarget", NULL);
RNA_def_struct_ui_text(srna, "Keyed Particle Target", "Target particle system for keyed particles.");
static EnumPropertyItem mode_items[] = {
{PTARGET_MODE_FRIEND, "FRIEND", 0, "Friend", ""},
{PTARGET_MODE_NEUTRAL, "NEUTRAL", 0, "Neutral", ""},
{PTARGET_MODE_ENEMY, "ENEMY", 0, "Enemy", ""},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "ParticleTarget", NULL);
RNA_def_struct_ui_text(srna, "Particle Target", "Target particle system.");
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_KeyedParticleTarget_name_get", "rna_KeyedParticleTarget_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Keyed particle target name.");
RNA_def_property_string_funcs(prop, "rna_ParticleTarget_name_get", "rna_ParticleTarget_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Particle target name.");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
@@ -1713,32 +1765,36 @@ static void rna_def_keyed_particle_target(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Target Object", "The object that has the target particle system (empty if same object).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_reset");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_target_reset");
prop= RNA_def_property(srna, "system", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "psys");
RNA_def_property_range(prop, 1, INT_MAX);
RNA_def_property_ui_text(prop, "Target Particle System", "The index of particle system on the target object.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_reset");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_target_reset");
prop= RNA_def_property(srna, "time", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "time");
RNA_def_property_range(prop, 0.0, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
RNA_def_property_ui_text(prop, "Time", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_redo");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_target_redo");
prop= RNA_def_property(srna, "duration", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "duration");
RNA_def_property_range(prop, 0.0, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
RNA_def_property_ui_text(prop, "Duration", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_redo");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_target_redo");
prop= RNA_def_property(srna, "valid", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYED_TARGET_VALID);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTARGET_VALID);
RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Valid", "Keyed particles target is valid.");
prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Mode", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_target_reset");
}
static void rna_def_particle_system(BlenderRNA *brna)
@@ -1751,9 +1807,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_PARTICLE_DATA);
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ParticleSystem_name_get", "rna_ParticleSystem_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Particle system name.");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
/* access to particle settings is redirected through functions */
@@ -1807,13 +1861,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Reactor Target Particle System", "For reactor systems, index of particle system on the target object.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* boids */
//prop= RNA_def_property(srna, "boids_surface_object", PROP_POINTER, PROP_NONE);
//RNA_def_property_pointer_sdna(prop, NULL, "keyed_ob");
//RNA_def_property_flag(prop, PROP_EDITABLE);
//RNA_def_property_ui_text(prop, "Boids Surface Object", "For boids physics systems, constrain boids to this object's surface.");
//RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* keyed */
prop= RNA_def_property(srna, "keyed_timing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_KEYED_TIMING);
@@ -1821,19 +1868,18 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Keyed timing", "Use key times");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
prop= RNA_def_property(srna, "keyed_targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "keyed_targets", NULL);
RNA_def_property_struct_type(prop, "KeyedParticleTarget");
RNA_def_property_ui_text(prop, "Keyed Targets", "Target particle systems for keyed particles");
prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "ParticleTarget");
RNA_def_property_ui_text(prop, "Targets", "Target particle systems.");
prop= RNA_def_property(srna, "active_keyed_target", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "KeyedParticleTarget");
RNA_def_property_pointer_funcs(prop, "rna_ParticleSystem_active_keyed_target_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed");
prop= RNA_def_property(srna, "active_particle_target", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ParticleTarget");
RNA_def_property_pointer_funcs(prop, "rna_ParticleSystem_active_particle_target_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Active Particle Target", "");
prop= RNA_def_property(srna, "active_keyed_target_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_ParticleSystem_active_keyed_target_index_get", "rna_ParticleSystem_active_keyed_target_index_set", "rna_ParticleSystem_active_keyed_target_index_range");
RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot.");
prop= RNA_def_property(srna, "active_particle_target_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_ParticleSystem_active_particle_target_index_get", "rna_ParticleSystem_active_particle_target_index_set", "rna_ParticleSystem_active_particle_target_index_range");
RNA_def_property_ui_text(prop, "Active Particle Target Index", "");
/* billboard */
@@ -1989,11 +2035,13 @@ static void rna_def_particle_system(BlenderRNA *brna)
void RNA_def_particle(BlenderRNA *brna)
{
rna_def_particle_target(brna);
rna_def_particle_hair_key(brna);
rna_def_particle_key(brna);
rna_def_child_particle(brna);
rna_def_particle(brna);
rna_def_keyed_particle_target(brna);
rna_def_particle_system(brna);
rna_def_particle_settings(brna);
}