Particle settings can now be pinned too:
* Particle system's are comparable to texture slots, which can only exist within an id block. Particle settings on the other hand are idblocks which should be pinnable just like textures. * When particle settings are pinned only properties that make sense without the actual particle system are shown in the particle panel.
This commit is contained in:
@@ -27,6 +27,8 @@ from properties_physics_common import basic_force_field_falloff_ui
|
||||
|
||||
|
||||
def particle_panel_enabled(context, psys):
|
||||
if psys == None:
|
||||
return True
|
||||
phystype = psys.settings.physics_type
|
||||
if psys.settings.type in ('EMITTER', 'REACTOR') and phystype in ('NO', 'KEYED'):
|
||||
return True
|
||||
@@ -37,11 +39,24 @@ def particle_panel_enabled(context, psys):
|
||||
def particle_panel_poll(cls, context):
|
||||
psys = context.particle_system
|
||||
engine = context.scene.render.engine
|
||||
if psys is None:
|
||||
settings = 0
|
||||
|
||||
if psys:
|
||||
settings = psys.settings
|
||||
elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
|
||||
settings = context.space_data.pin_id
|
||||
|
||||
if not settings:
|
||||
return False
|
||||
if psys.settings is None:
|
||||
return False
|
||||
return psys.settings.is_fluid == False and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
return settings.is_fluid == False and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def particle_get_settings(context):
|
||||
if context.particle_system:
|
||||
return context.particle_system.settings
|
||||
elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
|
||||
return context.space_data.pin_id
|
||||
return None
|
||||
|
||||
|
||||
class ParticleButtonsPanel():
|
||||
@@ -62,13 +77,14 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
engine = context.scene.render.engine
|
||||
return (context.particle_system or context.object) and (engine in cls.COMPAT_ENGINES)
|
||||
return (context.particle_system or context.object or context.space_data.pin_id) and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
psys = context.particle_system
|
||||
part = 0
|
||||
|
||||
if ob:
|
||||
row = layout.row()
|
||||
@@ -79,7 +95,21 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
|
||||
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
|
||||
col.operator("object.particle_system_remove", icon='ZOOMOUT', text="")
|
||||
|
||||
if psys and not psys.settings:
|
||||
if psys == None:
|
||||
part = particle_get_settings(context)
|
||||
|
||||
if part == None:
|
||||
return
|
||||
|
||||
layout.template_ID(context.space_data, "pin_id")
|
||||
|
||||
if part.is_fluid:
|
||||
layout.label(text="Settings used for fluid.")
|
||||
return
|
||||
|
||||
layout.prop(part, "type", text="Type")
|
||||
|
||||
elif not psys.settings:
|
||||
split = layout.split(percentage=0.32)
|
||||
|
||||
col = split.column()
|
||||
@@ -89,7 +119,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
|
||||
col = split.column()
|
||||
col.prop(psys, "name", text="")
|
||||
col.template_ID(psys, "settings", new="particle.new")
|
||||
elif psys:
|
||||
else:
|
||||
part = psys.settings
|
||||
|
||||
split = layout.split(percentage=0.32)
|
||||
@@ -110,39 +140,39 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
|
||||
#row.label(text="Viewport")
|
||||
#row.label(text="Render")
|
||||
|
||||
if part:
|
||||
if part.is_fluid:
|
||||
layout.label(text=str(part.count) + " fluid particles for this frame.")
|
||||
return
|
||||
if part.is_fluid:
|
||||
layout.label(text=str(part.count) + " fluid particles for this frame.")
|
||||
return
|
||||
|
||||
row = col.row()
|
||||
row.enabled = particle_panel_enabled(context, psys)
|
||||
row.prop(part, "type", text="")
|
||||
row.prop(psys, "seed")
|
||||
row = col.row()
|
||||
row.enabled = particle_panel_enabled(context, psys)
|
||||
row.prop(part, "type", text="")
|
||||
row.prop(psys, "seed")
|
||||
|
||||
split = layout.split(percentage=0.65)
|
||||
if part.type == 'HAIR':
|
||||
if psys.is_edited:
|
||||
split.operator("particle.edited_clear", text="Free Edit")
|
||||
else:
|
||||
row = split.row()
|
||||
row.enabled = particle_panel_enabled(context, psys)
|
||||
row.prop(part, "regrow_hair")
|
||||
row.prop(part, "use_advanced_hair")
|
||||
if part:
|
||||
split = layout.split(percentage=0.65)
|
||||
if part.type == 'HAIR':
|
||||
if psys != None and psys.is_edited:
|
||||
split.operator("particle.edited_clear", text="Free Edit")
|
||||
else:
|
||||
row = split.row()
|
||||
row.enabled = particle_panel_enabled(context, psys)
|
||||
row.prop(part, "hair_step")
|
||||
if psys.is_edited:
|
||||
if psys.is_global_hair:
|
||||
layout.operator("particle.connect_hair")
|
||||
layout.label(text="Hair is disconnected.")
|
||||
else:
|
||||
layout.operator("particle.disconnect_hair")
|
||||
layout.label(text="")
|
||||
elif part.type == 'REACTOR':
|
||||
split.enabled = particle_panel_enabled(context, psys)
|
||||
split.prop(psys, "reactor_target_object")
|
||||
split.prop(psys, "reactor_target_particle_system", text="Particle System")
|
||||
row.prop(part, "regrow_hair")
|
||||
row.prop(part, "use_advanced_hair")
|
||||
row = split.row()
|
||||
row.enabled = particle_panel_enabled(context, psys)
|
||||
row.prop(part, "hair_step")
|
||||
if psys != None and psys.is_edited:
|
||||
if psys.is_global_hair:
|
||||
layout.operator("particle.connect_hair")
|
||||
layout.label(text="Hair is disconnected.")
|
||||
else:
|
||||
layout.operator("particle.disconnect_hair")
|
||||
layout.label(text="")
|
||||
elif psys != None and part.type == 'REACTOR':
|
||||
split.enabled = particle_panel_enabled(context, psys)
|
||||
split.prop(psys, "reactor_target_object")
|
||||
split.prop(psys, "reactor_target_particle_system", text="Particle System")
|
||||
|
||||
|
||||
class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
|
||||
@@ -152,23 +182,23 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
psys = context.particle_system
|
||||
if psys is None:
|
||||
settings = particle_get_settings(context)
|
||||
|
||||
if settings is None:
|
||||
return False
|
||||
if psys.settings is None:
|
||||
return False
|
||||
if psys.settings.is_fluid:
|
||||
if settings.is_fluid:
|
||||
return False
|
||||
if particle_panel_poll(PARTICLE_PT_emission, context):
|
||||
return not context.particle_system.point_cache.use_external
|
||||
return psys == None or not context.particle_system.point_cache.use_external
|
||||
return False
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
layout.enabled = particle_panel_enabled(context, psys) and not psys.has_multiple_caches
|
||||
layout.enabled = particle_panel_enabled(context, psys) and (psys == None or not psys.has_multiple_caches)
|
||||
|
||||
row = layout.row()
|
||||
row.active = part.distribution != 'GRID'
|
||||
@@ -309,9 +339,11 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
|
||||
def poll(cls, context):
|
||||
if particle_panel_poll(PARTICLE_PT_velocity, context):
|
||||
psys = context.particle_system
|
||||
if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
|
||||
settings = particle_get_settings(context)
|
||||
|
||||
if settings.type == 'HAIR' and not settings.use_advanced_hair:
|
||||
return False
|
||||
return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.use_external
|
||||
return settings.physics_type != 'BOIDS' and (psys == None or not psys.point_cache.use_external)
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -319,7 +351,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
layout.enabled = particle_panel_enabled(context, psys)
|
||||
|
||||
@@ -359,9 +391,11 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
|
||||
def poll(cls, context):
|
||||
if particle_panel_poll(PARTICLE_PT_rotation, context):
|
||||
psys = context.particle_system
|
||||
if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
|
||||
settings = particle_get_settings(context)
|
||||
|
||||
if settings.type == 'HAIR' and not settings.use_advanced_hair:
|
||||
return False
|
||||
return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.use_external
|
||||
return settings.physics_type != 'BOIDS' and (psys == None or not psys.point_cache.use_external)
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -369,7 +403,10 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
if psys:
|
||||
part = psys.settings
|
||||
else:
|
||||
part = context.space_data.pin_id
|
||||
|
||||
layout.enabled = particle_panel_enabled(context, psys)
|
||||
|
||||
@@ -404,9 +441,11 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
|
||||
def poll(cls, context):
|
||||
if particle_panel_poll(PARTICLE_PT_physics, context):
|
||||
psys = context.particle_system
|
||||
if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
|
||||
settings = particle_get_settings(context)
|
||||
|
||||
if settings.type == 'HAIR' and not settings.use_advanced_hair:
|
||||
return False
|
||||
return not psys.point_cache.use_external
|
||||
return psys == None or not psys.point_cache.use_external
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -414,7 +453,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
layout.enabled = particle_panel_enabled(context, psys)
|
||||
|
||||
@@ -504,7 +543,8 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
|
||||
col = row.column()
|
||||
col.active = not psys.use_keyed_timing
|
||||
col.prop(part, "keyed_loops", text="Loops")
|
||||
row.prop(psys, "use_keyed_timing", text="Use Timing")
|
||||
if psys:
|
||||
row.prop(psys, "use_keyed_timing", text="Use Timing")
|
||||
|
||||
layout.label(text="Keys:")
|
||||
elif part.physics_type == 'BOIDS':
|
||||
@@ -555,7 +595,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
|
||||
col.prop(boids, "pitch", slider=True)
|
||||
col.prop(boids, "height", slider=True)
|
||||
|
||||
if part.physics_type == 'KEYED' or part.physics_type == 'BOIDS' or part.physics_type == 'FLUID':
|
||||
if psys and part.physics_type in ('KEYED', 'BOIDS', 'FLUID'):
|
||||
if part.physics_type == 'BOIDS':
|
||||
layout.label(text="Relations:")
|
||||
elif part.physics_type == 'FLUID':
|
||||
@@ -610,19 +650,19 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, bpy.types.Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
psys = context.particle_system
|
||||
settings = particle_get_settings(context)
|
||||
engine = context.scene.render.engine
|
||||
if psys is None:
|
||||
|
||||
if settings is None:
|
||||
return False
|
||||
if psys.settings is None:
|
||||
if psys != None and psys.point_cache.use_external:
|
||||
return False
|
||||
if psys.point_cache.use_external:
|
||||
return False
|
||||
return psys.settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
|
||||
return settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
boids = context.particle_system.settings.boids
|
||||
boids = particle_get_settings(context).boids
|
||||
|
||||
layout.enabled = particle_panel_enabled(context, context.particle_system)
|
||||
|
||||
@@ -890,7 +930,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
row = layout.row()
|
||||
row.prop(part, "draw_method", expand=True)
|
||||
@@ -949,7 +989,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
|
||||
layout = self.layout
|
||||
|
||||
psys = context.particle_system
|
||||
part = psys.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
layout.row().prop(part, "child_type", expand=True)
|
||||
|
||||
@@ -964,7 +1004,8 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
|
||||
|
||||
if part.child_type == 'INTERPOLATED':
|
||||
col = row.column()
|
||||
col.prop(psys, "child_seed", text="Seed")
|
||||
if psys:
|
||||
col.prop(psys, "child_seed", text="Seed")
|
||||
col.prop(part, "virtual_parents", slider=True)
|
||||
col.prop(part, "create_long_hair_children")
|
||||
else:
|
||||
@@ -989,7 +1030,8 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
|
||||
sub = col.column(align=True)
|
||||
sub.prop(part, "child_radius", text="Radius")
|
||||
sub.prop(part, "child_roundness", text="Roundness", slider=True)
|
||||
sub.prop(psys, "child_seed", text="Seed")
|
||||
if psys:
|
||||
sub.prop(psys, "child_seed", text="Seed")
|
||||
elif part.virtual_parents > 0.0:
|
||||
sub = col.column(align=True)
|
||||
sub.label(text="Parting not")
|
||||
@@ -1044,7 +1086,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, bpy.types.Panel):
|
||||
return particle_panel_poll(cls, context)
|
||||
|
||||
def draw(self, context):
|
||||
part = context.particle_system.settings
|
||||
part = particle_get_settings(context)
|
||||
effector_weights_ui(self, context, part.effector_weights)
|
||||
|
||||
if part.type == 'HAIR':
|
||||
@@ -1063,7 +1105,7 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, bpy.types.Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
part = context.particle_system.settings
|
||||
part = particle_get_settings(context)
|
||||
|
||||
row = layout.row()
|
||||
row.prop(part, "use_self_effect")
|
||||
@@ -1096,6 +1138,8 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.particle_system == None:
|
||||
return False
|
||||
return particle_panel_poll(cls, context)
|
||||
|
||||
def draw(self, context):
|
||||
|
@@ -307,7 +307,12 @@ static int buttons_context_path_particle(ButsContextPath *path)
|
||||
{
|
||||
Object *ob;
|
||||
ParticleSystem *psys;
|
||||
PointerRNA *ptr= &path->ptr[path->len-1];
|
||||
|
||||
/* if we already have (pinned) particle settings, we're done */
|
||||
if(RNA_struct_is_a(ptr->type, &RNA_ParticleSettings)) {
|
||||
return 1;
|
||||
}
|
||||
/* if we have an object, get the active particle system */
|
||||
if(buttons_context_path_object(path)) {
|
||||
ob= path->ptr[path->len-1].data;
|
||||
@@ -395,15 +400,25 @@ static int buttons_context_path_texture(ButsContextPath *path)
|
||||
}
|
||||
/* try particles */
|
||||
if((path->tex_ctx == SB_TEXC_PARTICLES) && buttons_context_path_particle(path)) {
|
||||
psys= path->ptr[path->len-1].data;
|
||||
|
||||
if(psys && psys->part && GS(psys->part->id.name)==ID_PA) {
|
||||
tex= give_current_particle_texture(psys->part);
|
||||
if(path->ptr[path->len-1].type == &RNA_ParticleSettings) {
|
||||
ParticleSettings *part = path->ptr[path->len-1].data;
|
||||
|
||||
tex= give_current_particle_texture(part);
|
||||
RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
|
||||
path->len++;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
psys= path->ptr[path->len-1].data;
|
||||
|
||||
if(psys && psys->part && GS(psys->part->id.name)==ID_PA) {
|
||||
tex= give_current_particle_texture(psys->part);
|
||||
|
||||
RNA_id_pointer_create(&tex->id, &path->ptr[path->len]);
|
||||
path->len++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* try material */
|
||||
if(buttons_context_path_material(path)) {
|
||||
@@ -930,6 +945,14 @@ ID *buttons_context_id_path(const bContext *C)
|
||||
for(a=path->len-1; a>=0; a--) {
|
||||
ptr= &path->ptr[a];
|
||||
|
||||
/* pin particle settings instead of system, since only settings are an idblock*/
|
||||
if(sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) {
|
||||
if(ptr->type == &RNA_ParticleSystem && ptr->data) {
|
||||
ParticleSystem *psys = (ParticleSystem *)ptr->data;
|
||||
return &psys->part->id;
|
||||
}
|
||||
}
|
||||
|
||||
if(ptr->id.data) {
|
||||
return ptr->id.data;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user