From 7b547f7ce7351548a5dd4518ae1fc1ad9a726cbd Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 27 Jun 2009 15:41:47 +0000 Subject: Particle ID block controls: * Adding/removing particle systems to an object. * Changing of particle settings. * Currently showing an object's particle systems in a list (like materials). --- release/ui/buttons_particle.py | 71 ++++++++------ source/blender/blenkernel/BKE_particle.h | 3 + source/blender/blenkernel/intern/depsgraph.c | 2 +- source/blender/blenkernel/intern/modifier.c | 3 + source/blender/blenkernel/intern/particle.c | 74 +++++++++++++- .../blender/editors/space_buttons/buttons_intern.h | 5 + source/blender/editors/space_buttons/buttons_ops.c | 107 +++++++++++++++++++++ .../blender/editors/space_buttons/space_buttons.c | 5 + source/blender/makesrna/intern/rna_object.c | 23 +++++ source/blender/makesrna/intern/rna_particle.c | 33 ++++++- 10 files changed, 292 insertions(+), 34 deletions(-) diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py index 378689e8202..e51df6ef7fd 100644 --- a/release/ui/buttons_particle.py +++ b/release/ui/buttons_particle.py @@ -7,6 +7,7 @@ def particle_panel_enabled(psys): def particle_panel_poll(context): psys = context.particle_system if psys==None: return False + if psys.settings==None: return False return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR') class ParticleButtonsPanel(bpy.types.Panel): @@ -29,42 +30,51 @@ class PARTICLE_PT_particles(ParticleButtonsPanel): ob = context.object psys = context.particle_system - split = layout.split(percentage=0.65) + if ob: + row = layout.row() - if psys: - split.template_ID(psys, "settings") + row.template_list(ob, "particle_systems", "active_particle_system_index") + + col = row.column(align=True) + col.itemO("OBJECT_OT_particle_system_slot_add", icon="ICON_ZOOMIN", text="") + col.itemO("OBJECT_OT_particle_system_slot_remove", icon="ICON_ZOOMOUT", text="") if psys: + split = layout.split(percentage=0.65) + + split.template_ID(psys, "settings", new="PARTICLE_OT_new") + #row = layout.row() #row.itemL(text="Viewport") #row.itemL(text="Render") part = psys.settings - ptype = psys.settings.type - if ptype not in ('EMITTER', 'REACTOR', 'HAIR'): - layout.itemL(text="No settings for fluid particles") - return + if part: + ptype = psys.settings.type + if ptype not in ('EMITTER', 'REACTOR', 'HAIR'): + layout.itemL(text="No settings for fluid particles") + return + + split = layout.split(percentage=0.65) - split = layout.split(percentage=0.65) - - split.enabled = particle_panel_enabled(psys) - split.itemR(part, "type") - split.itemR(psys, "seed") - - split = layout.split(percentage=0.65) - if part.type=='HAIR': - if psys.editable==True: - split.itemO("PARTICLE_OT_editable_set", text="Free Edit") - else: - split.itemO("PARTICLE_OT_editable_set", text="Make Editable") - row = split.row() - row.enabled = particle_panel_enabled(psys) - row.itemR(part, "hair_step") - elif part.type=='REACTOR': split.enabled = particle_panel_enabled(psys) - split.itemR(psys, "reactor_target_object") - split.itemR(psys, "reactor_target_particle_system", text="Particle System") + split.itemR(part, "type") + split.itemR(psys, "seed") + + split = layout.split(percentage=0.65) + if part.type=='HAIR': + if psys.editable==True: + split.itemO("PARTICLE_OT_editable_set", text="Free Edit") + else: + split.itemO("PARTICLE_OT_editable_set", text="Make Editable") + row = split.row() + row.enabled = particle_panel_enabled(psys) + row.itemR(part, "hair_step") + elif part.type=='REACTOR': + split.enabled = particle_panel_enabled(psys) + split.itemR(psys, "reactor_target_object") + split.itemR(psys, "reactor_target_particle_system", text="Particle System") class PARTICLE_PT_emission(ParticleButtonsPanel): __idname__= "PARTICLE_PT_emission" @@ -120,6 +130,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel): def poll(self, context): psys = context.particle_system if psys==None: return False + if psys.settings==None: return False return psys.settings.type in ('EMITTER', 'REACTOR') def draw(self, context): @@ -287,7 +298,10 @@ class PARTICLE_PT_render(ParticleButtonsPanel): __label__ = "Render" def poll(self, context): - return (context.particle_system != None) + psys = context.particle_system + if psys==None: return False + if psys.settings==None: return False + return True; def draw(self, context): layout = self.layout @@ -421,7 +435,10 @@ class PARTICLE_PT_draw(ParticleButtonsPanel): __default_closed__ = True def poll(self, context): - return (context.particle_system != None) + psys = context.particle_system + if psys==None: return False + if psys.settings==None: return False + return True; def draw(self, context): layout = self.layout diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 08aa111e0e6..4d9916b9557 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -217,6 +217,7 @@ char *psys_menu_string(struct Object *ob, int for_sb); struct ParticleSystem *psys_get_current(struct Object *ob); short psys_get_current_num(struct Object *ob); +void psys_set_current_num(Object *ob, int index); struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); //struct ParticleSystem *psys_get(struct Object *ob, int index); struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index); @@ -250,6 +251,8 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); +void object_add_particle_system_slot(struct Scene *scene, struct Object *ob); +void object_remove_particle_system_slot(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index b57b8b7a6da..a36b825293e 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -559,7 +559,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); - if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + if(!psys_check_enabled(ob, psys)) continue; if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob && diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 1a6f57e75c4..80a9f173d6a 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6295,6 +6295,9 @@ CustomDataMask particleSystemModifier_requiredDataMask(Object *ob, ModifierData MTex *mtex; int i; + if(!psmd->psys->part) + return 0; + ma= give_current_material(ob, psmd->psys->part->omat); if(ma) { for(i=0; iparticlesystem.first, i=0; psys; psys=psys->next, i++) { + if(i == index - 1) + psys->flag |= PSYS_CURRENT; + else + psys->flag &= ~PSYS_CURRENT; + } +} Object *psys_find_object(Scene *scene, ParticleSystem *psys) { Base *base = scene->base.first; @@ -307,7 +321,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) ParticleSystemModifierData *psmd; Mesh *me; - if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part) return 0; if(ob->type == OB_MESH) { @@ -2915,6 +2929,61 @@ void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleDa /************************************************/ /* ParticleSettings handling */ /************************************************/ +void object_add_particle_system_slot(Scene *scene, Object *ob) +{ + ParticleSystem *psys; + ModifierData *md; + ParticleSystemModifierData *psmd; + + if(!ob || ob->type != OB_MESH) + return; + + psys = ob->particlesystem.first; + for(; psys; psys=psys->next) + psys->flag &= ~PSYS_CURRENT; + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + BLI_addtail(&ob->particlesystem, psys); + + psys->part = psys_new_settings("PSys", NULL); + + md= modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + psmd= (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&ob->modifiers, md); + + psys->totpart=0; + psys->flag = PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(scene,ob,scene->r.cfra+1,0.0); + + DAG_scene_sort(scene); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +} +void object_remove_particle_system_slot(Scene *scene, Object *ob) +{ + ParticleSystem *psys = psys_get_current(ob); + ParticleSystemModifierData *psmd; + + if(!psys) + return; + + /* clear modifier */ + psmd= psys_get_modifier(ob, psys); + BLI_remlink(&ob->modifiers, psmd); + modifier_free((ModifierData *)psmd); + + /* clear particle system */ + BLI_remlink(&ob->particlesystem, psys); + psys_free(ob,psys); + + if(ob->particlesystem.first) + ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT; + + DAG_scene_sort(scene); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); +} static void default_particle_settings(ParticleSettings *part) { int i; @@ -3001,6 +3070,9 @@ ParticleSettings *psys_new_settings(char *name, Main *main) { ParticleSettings *part; + if(main==NULL) + main = G.main; + part= alloc_libblock(&main->particle, ID_PA, name); default_particle_settings(part); diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h index b213e4288be..13ea778fb00 100644 --- a/source/blender/editors/space_buttons/buttons_intern.h +++ b/source/blender/editors/space_buttons/buttons_intern.h @@ -71,5 +71,10 @@ void MATERIAL_OT_new(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); void WORLD_OT_new(struct wmOperatorType *ot); +void OBJECT_OT_particle_system_slot_add(struct wmOperatorType *ot); +void OBJECT_OT_particle_system_slot_remove(struct wmOperatorType *ot); + +void PARTICLE_OT_new(struct wmOperatorType *ot); + #endif /* ED_BUTTONS_INTERN_H */ diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 6755a2be1b7..6ca92674c6e 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -42,6 +42,7 @@ #include "BKE_font.h" #include "BKE_library.h" #include "BKE_material.h" +#include "BKE_particle.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_world.h" @@ -407,3 +408,109 @@ void WORLD_OT_new(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } + + +/********************** particle system slot operators *********************/ + +static int particle_system_slot_add_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Scene *scene = CTX_data_scene(C); + + if(!scene || !ob) + return OPERATOR_CANCELLED; + + object_add_particle_system_slot(scene, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_particle_system_slot_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Particle System Slot"; + ot->idname= "OBJECT_OT_particle_system_slot_add"; + + /* api callbacks */ + ot->exec= particle_system_slot_add_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int particle_system_slot_remove_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + Scene *scene = CTX_data_scene(C); + + if(!scene || !ob) + return OPERATOR_CANCELLED; + + object_remove_particle_system_slot(scene, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_particle_system_slot_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Particle System Slot"; + ot->idname= "OBJECT_OT_particle_system_slot_remove"; + + /* api callbacks */ + ot->exec= particle_system_slot_remove_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************** new particle settings operator *********************/ + +static int new_particle_settings_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ParticleSettings *part= CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings).data; + Object *ob; + PointerRNA ptr; + + /* add or copy particle setting */ + if(part) + part= psys_copy_settings(part); + else + part= psys_new_settings("PSys", NULL); + + /* attempt to assign to material slot */ + ptr= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + + if(ptr.data) { + ParticleSystem *psys = (ParticleSystem*)ptr.data; + ob= ptr.id.data; + + if(psys->part) + psys->part->id.us--; + + psys->part = part; + + DAG_scene_sort(scene); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); + } + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_new(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "New Particle Settings"; + ot->idname= "PARTICLE_OT_new"; + + /* api callbacks */ + ot->exec= new_particle_settings_exec; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 483a1dc6100..7954d5254cc 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -219,6 +219,11 @@ void buttons_operatortypes(void) WM_operatortype_append(MATERIAL_OT_new); WM_operatortype_append(TEXTURE_OT_new); WM_operatortype_append(WORLD_OT_new); + + WM_operatortype_append(OBJECT_OT_particle_system_slot_add); + WM_operatortype_append(OBJECT_OT_particle_system_slot_remove); + + WM_operatortype_append(PARTICLE_OT_new); } void buttons_keymap(struct wmWindowManager *wm) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 5b553469bc8..9b3100c733b 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -241,6 +241,25 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MaterialSlot, ob->mat+ob->actcol); } +static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int *min, int *max) +{ + Object *ob= (Object*)ptr->id.data; + *min= 1; + *max= BLI_countlist(&ob->particlesystem); +} + +static int rna_Object_active_particle_system_index_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + return psys_get_current_num(ob) + 1; +} + +static void rna_Object_active_particle_system_index_set(struct PointerRNA *ptr, int value) +{ + Object *ob= (Object*)ptr->id.data; + psys_set_current_num(ob, value); +} + #if 0 static void rna_Object_active_material_set(PointerRNA *ptr, PointerRNA value) { @@ -929,6 +948,10 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_Object_active_particle_system_get", NULL, NULL); RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed"); + prop= RNA_def_property(srna, "active_particle_system_index", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_Object_active_particle_system_index_get", "rna_Object_active_particle_system_index_set", "rna_Object_active_particle_system_index_range"); + RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot."); + /* restrict */ prop= RNA_def_property(srna, "restrict_view", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index ae53c815ed9..d60a215b498 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -81,13 +81,11 @@ static void rna_Particle_reset(bContext *C, PointerRNA *ptr) if(ob) { DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - //WM_event_add_notifier(C, NC_SCENE|ND_CACHE_PHYSICS, scene); } } else { part = ptr->id.data; psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET); - //WM_event_add_notifier(C, NC_SCENE|ND_CACHE_PHYSICS, scene); } } @@ -104,13 +102,11 @@ static void rna_Particle_change_type(bContext *C, PointerRNA *ptr) if(ob) { DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - //WM_event_add_notifier(C, NC_SCENE|ND_CACHE_PHYSICS, scene); } } else { part = ptr->id.data; psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_TYPE); - //WM_event_add_notifier(C, NC_SCENE|ND_CACHE_PHYSICS, scene); } } @@ -134,6 +130,27 @@ static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr) psys_flush_particle_settings(scene, part, PSYS_RECALC_CHILD); } } +static PointerRNA rna_particle_settings_get(PointerRNA *ptr) +{ + Object *ob= (Object*)ptr->id.data; + ParticleSettings *part = psys_get_current(ob)->part; + + return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part); +} + +static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value) +{ + Object *ob= (Object*)ptr->id.data; + ParticleSystem *psys = psys_get_current(ob); + + if(psys->part) + psys->part->id.us--; + + psys->part = (ParticleSettings *)value.data; + + if(psys->part) + psys->part->id.us++; +} static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value) { ParticleSettings *settings = (ParticleSettings*)ptr->data; @@ -1493,9 +1510,15 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_struct_name_property(srna, prop); + /* access to particle settings is redirected through functions */ + /* to allow proper id-buttons functionality */ prop= RNA_def_property(srna, "settings", PROP_POINTER, PROP_NEVER_NULL); - RNA_def_property_pointer_sdna(prop, NULL, "part"); + //RNA_def_property_pointer_sdna(prop, NULL, "part"); + RNA_def_property_struct_type(prop, "ParticleSettings"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_particle_settings_get", "rna_particle_settings_set", NULL); RNA_def_property_ui_text(prop, "Settings", "Particle system settings."); + RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset"); prop= RNA_def_property(srna, "particles", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "particles", "totpart"); -- cgit v1.2.3