4 def particle_panel_enabled(psys):
5 return psys.point_cache.baked==False and psys.editable==False
7 def particle_panel_poll(context):
8 psys = context.particle_system
9 if psys==None: return False
10 return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
12 class ParticleButtonsPanel(bpy.types.Panel):
13 __space_type__ = "BUTTONS_WINDOW"
14 __region_type__ = "WINDOW"
15 __context__ = "particle"
17 def poll(self, context):
18 return particle_panel_poll(context)
20 class PARTICLE_PT_particles(ParticleButtonsPanel):
21 __idname__= "PARTICLE_PT_particles"
22 __label__ = "Particle System"
24 def poll(self, context):
25 return (context.particle_system or context.object)
27 def draw(self, context):
30 psys = context.particle_system
32 split = layout.split(percentage=0.65)
35 split.template_ID(context, psys, "settings")
39 #row.itemL(text="Viewport")
40 #row.itemL(text="Render")
43 ptype = psys.settings.type
45 if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
46 layout.itemL(text="No settings for fluid particles")
49 split = layout.split(percentage=0.65)
51 split.enabled = particle_panel_enabled(psys)
52 split.itemR(part, "type")
53 split.itemR(psys, "seed")
55 split = layout.split(percentage=0.65)
57 if psys.editable==True:
58 split.itemO("PARTICLE_OT_editable_set", text="Free Edit")
60 split.itemO("PARTICLE_OT_editable_set", text="Make Editable")
62 row.enabled = particle_panel_enabled(psys)
63 row.itemR(part, "hair_step")
64 elif part.type=='REACTOR':
65 split.enabled = particle_panel_enabled(psys)
66 split.itemR(psys, "reactor_target_object")
67 split.itemR(psys, "reactor_target_particle_system", text="Particle System")
69 class PARTICLE_PT_emission(ParticleButtonsPanel):
70 __idname__= "PARTICLE_PT_emission"
71 __label__ = "Emission"
73 def draw(self, context):
76 psys = context.particle_system
79 layout.enabled = particle_panel_enabled(psys)
82 row.itemR(part, "amount")
84 split = layout.split()
86 col = split.column(align=True)
87 col.itemR(part, "start")
88 col.itemR(part, "end")
90 col = split.column(align=True)
91 col.itemR(part, "lifetime")
92 col.itemR(part, "random_lifetime", slider=True)
94 layout.row().itemL(text="Emit From:")
97 row.itemR(part, "emit_from", expand=True)
99 row.itemR(part, "trand")
100 if part.distribution!='GRID':
101 row.itemR(part, "even_distribution")
103 if part.emit_from=='FACE' or part.emit_from=='VOLUME':
105 row.itemR(part, "distribution", expand=True)
109 if part.distribution=='JIT':
110 row.itemR(part, "userjit", text="Particles/Face")
111 row.itemR(part, "jitter_factor", text="Jittering Amount", slider=True)
112 elif part.distribution=='GRID':
113 row.itemR(part, "grid_resolution")
115 class PARTICLE_PT_cache(ParticleButtonsPanel):
116 __idname__= "PARTICLE_PT_cache"
118 __default_closed__ = True
120 def poll(self, context):
121 psys = context.particle_system
122 if psys==None: return False
123 return psys.settings.type in ('EMITTER', 'REACTOR')
125 def draw(self, context):
128 psys = context.particle_system
130 cache = psys.point_cache
133 row.itemR(cache, "name", text="")
135 row.itemL(text="Cache is outdated.")
141 if cache.baked == True:
142 row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
144 row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
147 row.enabled = particle_panel_enabled(psys)
148 row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
149 if cache.autocache == 0:
150 row.itemO("PTCACHE_OT_cache_particle_system", text="Cache to Current Frame")
153 row.enabled = particle_panel_enabled(psys)
154 #row.itemR(cache, "autocache")
155 row.itemR(cache, "disk_cache")
156 row.itemL(text=cache.info)
158 # for particles these are figured out automatically
159 #row.itemR(cache, "start_frame")
160 #row.itemR(cache, "end_frame")
162 class PARTICLE_PT_initial(ParticleButtonsPanel):
163 __idname__= "PARTICLE_PT_initial"
164 __label__ = "Velocity"
166 def draw(self, context):
169 psys = context.particle_system
172 layout.enabled = particle_panel_enabled(psys)
174 layout.row().itemL(text="Direction:")
176 split = layout.split()
179 sub.itemR(part, "normal_factor")
180 if part.emit_from=='PARTICLE':
181 sub.itemR(part, "particle_factor")
183 sub.itemR(part, "object_factor", slider=True)
184 sub.itemR(part, "random_factor")
185 sub.itemR(part, "tangent_factor")
186 sub.itemR(part, "tangent_phase", slider=True)
189 sub.itemL(text="TODO:")
190 sub.itemL(text="Object aligned")
191 sub.itemL(text="direction: X, Y, Z")
193 if part.type=='REACTOR':
194 sub.itemR(part, "reactor_factor")
195 sub.itemR(part, "reaction_shape", slider=True)
199 layout.row().itemL(text="Rotation:")
200 split = layout.split()
204 sub.itemR(part, "rotation_mode", text="Axis")
205 split = layout.split()
208 sub.itemR(part, "rotation_dynamic")
209 sub.itemR(part, "random_rotation_factor", slider=True)
211 sub.itemR(part, "phase_factor", slider=True)
212 sub.itemR(part, "random_phase_factor", text="Random", slider=True)
214 layout.row().itemL(text="Angular velocity:")
215 layout.row().itemR(part, "angular_velocity_mode", expand=True)
216 split = layout.split()
220 sub.itemR(part, "angular_velocity_factor", text="")
222 class PARTICLE_PT_physics(ParticleButtonsPanel):
223 __idname__= "PARTICLE_PT_physics"
224 __label__ = "Physics"
226 def draw(self, context):
229 psys = context.particle_system
232 layout.enabled = layout.enabled = particle_panel_enabled(psys)
235 row.itemR(part, "physics_type", expand=True)
236 if part.physics_type != 'NO':
237 layout.itemR(part, "effector_group")
240 col = row.column(align=True)
241 col.itemR(part, "particle_size")
242 col.itemR(part, "random_size", slider=True)
243 col = row.column(align=True)
244 col.itemR(part, "mass")
245 col.itemR(part, "sizemass", text="Multiply mass with size")
247 split = layout.split()
251 if part.physics_type == 'NEWTON':
253 sub.itemL(text="Forces:")
254 sub.itemR(part, "brownian_factor")
255 sub.itemR(part, "drag_factor", slider=True)
256 sub.itemR(part, "damp_factor", slider=True)
257 sub.itemR(part, "integrator")
259 sub.itemR(part, "acceleration")
261 elif part.physics_type == 'KEYED':
262 sub.itemR(psys, "keyed_first")
263 if psys.keyed_first==True:
264 sub.itemR(psys, "timed_keys", text="Key timing")
266 sub.itemR(part, "keyed_time")
268 sub.itemL(text="Next key from object:")
269 sub.itemR(psys, "keyed_object", text="")
270 sub.itemR(psys, "keyed_particle_system")
272 if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
274 sub.itemR(part, "size_deflect")
275 sub.itemR(part, "die_on_collision")
276 sub.itemR(part, "sticky")
278 class PARTICLE_PT_render(ParticleButtonsPanel):
279 __idname__= "PARTICLE_PT_render"
282 def poll(self, context):
283 return (context.particle_system != None)
285 def draw(self, context):
288 psys = context.particle_system
292 row.itemR(part, "material")
293 row.itemR(psys, "parent");
295 split = layout.split()
298 sub.itemR(part, "emitter");
299 sub.itemR(part, "parent");
301 sub.itemR(part, "unborn");
302 sub.itemR(part, "died");
305 row.itemR(part, "ren_as", expand=True)
307 split = layout.split()
311 if part.ren_as == 'LINE':
312 sub.itemR(part, "line_length_tail")
313 sub.itemR(part, "line_length_head")
315 sub.itemR(part, "velocity_length")
316 elif part.ren_as == 'PATH':
318 if (part.type!='HAIR' and psys.point_cache.baked==False):
320 box.itemL(text="Baked or keyed particles needed for correct rendering.")
323 sub.itemR(part, "render_strand")
324 colsub = sub.column()
325 colsub.active = part.render_strand == False
326 colsub.itemR(part, "render_adaptive")
327 colsub = sub.column()
328 colsub.active = part.render_adaptive or part.render_strand == True
329 colsub.itemR(part, "adaptive_angle")
330 colsub = sub.column()
331 colsub.active = part.render_adaptive == True and part.render_strand == False
332 colsub.itemR(part, "adaptive_pix")
333 sub.itemR(part, "hair_bspline")
334 sub.itemR(part, "render_step", text="Steps")
336 sub.itemL(text="Length:")
337 sub.itemR(part, "abs_length", text="Absolute")
338 sub.itemR(part, "absolute_length", text="Maximum")
339 sub.itemR(part, "random_length", text="Random", slider=True)
342 #row.itemR(part, "timed_path")
343 #col = row.column(align=True)
344 #col.active = part.timed_path == True
345 #col.itemR(part, "line_length_tail", text="Start")
346 #col.itemR(part, "line_length_head", text="End")
351 if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
352 layout.itemR(part, "enable_simplify")
353 if part.enable_simplify==True:
355 row.itemR(part, "simplify_refsize")
356 row.itemR(part, "simplify_rate")
357 row.itemR(part, "simplify_transition")
359 row.itemR(part, "viewport")
361 subrow.active = part.viewport==True
362 subrow.itemR(part, "simplify_viewport")
365 elif part.ren_as == 'OBJECT':
366 #sub = split.column()
367 sub.itemR(part, "dupli_object")
368 elif part.ren_as == 'GROUP':
369 sub.itemR(part, "dupli_group")
370 split = layout.split()
372 sub.itemR(part, "whole_group")
374 colsub = sub.column()
375 colsub.active = part.whole_group == False
376 colsub.itemR(part, "rand_group")
378 elif part.ren_as == 'BILLBOARD':
379 sub.itemL(text="Align:")
382 row.itemR(part, "billboard_align", expand=True)
383 row.itemR(part, "billboard_lock", text="Lock")
385 row.itemR(part, "billboard_object")
388 col = row.column(align=True)
389 col.itemL(text="Tilt:")
390 col.itemR(part, "billboard_tilt", text="Angle", slider=True)
391 col.itemR(part, "billboard_random_tilt", slider=True)
393 col.itemR(part, "billboard_offset")
396 row.itemR(psys, "billboard_normal_uv")
398 row.itemR(psys, "billboard_time_index_uv")
401 row.itemL(text="Split uv's:")
402 row.itemR(part, "billboard_uv_split", text="Number of splits")
404 row.itemR(psys, "billboard_split_uv")
406 row.itemL(text="Animate:")
407 row.itemR(part, "billboard_animation", expand=True)
408 row.itemL(text="Offset:")
409 row.itemR(part, "billboard_split_offset", expand=True)
411 class PARTICLE_PT_draw(ParticleButtonsPanel):
412 __idname__= "PARTICLE_PT_draw"
413 __label__ = "Display"
414 __default_closed__ = True
416 def poll(self, context):
417 return (context.particle_system != None)
419 def draw(self, context):
422 psys = context.particle_system
426 row.itemR(part, "draw_as", expand=True)
428 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
431 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
433 if path and part.type!='HAIR' and psys.point_cache.baked==False:
435 box.itemL(text="Baked or keyed particles needed for correct drawing.")
439 row.itemR(part, "display", slider=True)
440 if part.draw_as!='RENDER' or part.ren_as=='HALO':
441 row.itemR(part, "draw_size")
447 col.itemR(part, "show_size")
448 col.itemR(part, "velocity")
449 col.itemR(part, "num")
450 if part.physics_type == 'BOIDS':
451 col.itemR(part, "draw_health")
456 box.itemR(part, "draw_step")
458 col.itemR(part, "material_color", text="Use material color")
459 subcol = col.column()
460 subcol.active = part.material_color==False
461 #subcol.itemL(text="color")
462 #subcol.itemL(text="Override material color")
464 class PARTICLE_PT_children(ParticleButtonsPanel):
465 __idname__= "PARTICLE_PT_children"
466 __label__ = "Children"
467 __default_closed__ = True
469 def draw(self, context):
472 psys = context.particle_system
475 layout.row().itemR(part, "child_type", expand=True)
477 if part.child_type=='NONE':
482 col = row.column(align=True)
483 col.itemR(part, "child_nbr", text="Display")
484 col.itemR(part, "rendered_child_nbr", text="Render")
486 col = row.column(align=True)
488 if part.child_type=='FACES':
489 col.itemR(part, "virtual_parents", slider=True)
491 col.itemR(part, "child_radius", text="Radius")
492 col.itemR(part, "child_roundness", text="Roundness", slider=True)
494 col = row.column(align=True)
495 col.itemR(part, "child_size", text="Size")
496 col.itemR(part, "child_random_size", text="Random")
498 layout.row().itemL(text="Effects:")
502 col = row.column(align=True)
503 col.itemR(part, "clump_factor", slider=True)
504 col.itemR(part, "clumppow", slider=True)
506 col = row.column(align=True)
507 col.itemR(part, "rough_endpoint")
508 col.itemR(part, "rough_end_shape")
512 col = row.column(align=True)
513 col.itemR(part, "rough1")
514 col.itemR(part, "rough1_size")
516 col = row.column(align=True)
517 col.itemR(part, "rough2")
518 col.itemR(part, "rough2_size")
519 col.itemR(part, "rough2_thres", slider=True)
521 layout.row().itemL(text="Kink:")
522 layout.row().itemR(part, "kink", expand=True)
524 split = layout.split()
527 sub.itemR(part, "kink_amplitude")
528 sub.itemR(part, "kink_frequency")
530 sub.itemR(part, "kink_shape", slider=True)
532 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
533 __idname__= "PARTICLE_PT_vertexgroups"
534 __label__ = "Vertexgroups"
535 __default_closed__ = True
537 def draw(self, context):
540 psys = context.particle_system
543 layout.itemL(text="Nothing here yet.")
546 #row.itemL(text="Vertex Group")
547 #row.itemL(text="Negate")
551 #row.itemR(psys, "vertex_group_density")
552 #row.itemR(psys, "vertex_group_density_negate", text="")
555 #row.itemR(psys, "vertex_group_velocity")
556 #row.itemR(psys, "vertex_group_velocity_negate", text="")
559 #row.itemR(psys, "vertex_group_length")
560 #row.itemR(psys, "vertex_group_length_negate", text="")
563 #row.itemR(psys, "vertex_group_clump")
564 #row.itemR(psys, "vertex_group_clump_negate", text="")
567 #row.itemR(psys, "vertex_group_kink")
568 #row.itemR(psys, "vertex_group_kink_negate", text="")
571 #row.itemR(psys, "vertex_group_roughness1")
572 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
575 #row.itemR(psys, "vertex_group_roughness2")
576 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
579 #row.itemR(psys, "vertex_group_roughness_end")
580 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
583 #row.itemR(psys, "vertex_group_size")
584 #row.itemR(psys, "vertex_group_size_negate", text="")
587 #row.itemR(psys, "vertex_group_tangent")
588 #row.itemR(psys, "vertex_group_tangent_negate", text="")
591 #row.itemR(psys, "vertex_group_rotation")
592 #row.itemR(psys, "vertex_group_rotation_negate", text="")
595 #row.itemR(psys, "vertex_group_field")
596 #row.itemR(psys, "vertex_group_field_negate", text="")
598 bpy.types.register(PARTICLE_PT_particles)
599 bpy.types.register(PARTICLE_PT_cache)
600 bpy.types.register(PARTICLE_PT_emission)
601 bpy.types.register(PARTICLE_PT_initial)
602 bpy.types.register(PARTICLE_PT_physics)
603 bpy.types.register(PARTICLE_PT_render)
604 bpy.types.register(PARTICLE_PT_draw)
605 bpy.types.register(PARTICLE_PT_children)
606 bpy.types.register(PARTICLE_PT_vertexgroups)