* Adding/removing particle systems to an object.
* Changing of particle settings.
* Currently showing an object's particle systems in a list (like materials).
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):
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"
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):
__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
__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
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);
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);
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 &&
MTex *mtex;
int i;
+ if(!psmd->psys->part)
+ return 0;
+
ma= give_current_material(ob, psmd->psys->part->omat);
if(ma) {
for(i=0; i<MAX_MTEX; i++) {
return i;
}
+void psys_set_current_num(Object *ob, int index)
+{
+ ParticleSystem *psys;
+ short i;
+
+ if(ob==0) return;
+
+ for(psys=ob->particlesystem.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;
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) {
/************************************************/
/* 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;
{
ParticleSettings *part;
+ if(main==NULL)
+ main = G.main;
+
part= alloc_libblock(&main->particle, ID_PA, name);
default_particle_settings(part);
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 */
#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"
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;
+}
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)
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)
{
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);
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);
}
}
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);
}
}
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;
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");