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:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
62
source/blender/blenkernel/BKE_boids.h
Normal file
62
source/blender/blenkernel/BKE_boids.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
1526
source/blender/blenkernel/intern/boids.c
Normal file
1526
source/blender/blenkernel/intern/boids.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
433
source/blender/editors/physics/physics_boids.c
Normal file
433
source/blender/editors/physics/physics_boids.c
Normal 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);
|
||||
}
|
||||
@@ -93,6 +93,7 @@ void ED_spacetypes_init(void)
|
||||
ED_operatortypes_marker();
|
||||
ED_operatortypes_pointcache();
|
||||
ED_operatortypes_fluid();
|
||||
ED_operatortypes_boids();
|
||||
|
||||
ui_view2d_operatortypes();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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},
|
||||
|
||||
615
source/blender/makesrna/intern/rna_boid.c
Normal file
615
source/blender/makesrna/intern/rna_boid.c
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user