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
291 layout.itemR(part, "material")
293 split = layout.split()
296 sub.itemR(part, "emitter");
297 sub.itemR(part, "parent");
299 sub.itemR(part, "unborn");
300 sub.itemR(part, "died");
303 row.itemR(part, "ren_as", expand=True)
305 split = layout.split()
309 if part.ren_as == 'LINE':
310 sub.itemR(part, "line_length_tail")
311 sub.itemR(part, "line_length_head")
313 sub.itemR(part, "velocity_length")
314 elif part.ren_as == 'PATH':
316 if (part.type!='HAIR' and psys.point_cache.baked==False):
318 box.itemL(text="Baked or keyed particles needed for correct rendering.")
321 sub.itemR(part, "render_strand")
322 colsub = sub.column()
323 colsub.active = part.render_strand == False
324 colsub.itemR(part, "render_adaptive")
325 colsub = sub.column()
326 colsub.active = part.render_adaptive or part.render_strand == True
327 colsub.itemR(part, "adaptive_angle")
328 colsub = sub.column()
329 colsub.active = part.render_adaptive == True and part.render_strand == False
330 colsub.itemR(part, "adaptive_pix")
331 sub.itemR(part, "hair_bspline")
332 sub.itemR(part, "render_step", text="Steps")
334 sub.itemL(text="Length:")
335 sub.itemR(part, "abs_length", text="Absolute")
336 sub.itemR(part, "absolute_length", text="Maximum")
337 sub.itemR(part, "random_length", text="Random", slider=True)
340 #row.itemR(part, "timed_path")
341 #col = row.column(align=True)
342 #col.active = part.timed_path == True
343 #col.itemR(part, "line_length_tail", text="Start")
344 #col.itemR(part, "line_length_head", text="End")
349 if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
350 layout.itemR(part, "enable_simplify")
351 if part.enable_simplify==True:
353 row.itemR(part, "simplify_refsize")
354 row.itemR(part, "simplify_rate")
355 row.itemR(part, "simplify_transition")
357 row.itemR(part, "viewport")
359 subrow.active = part.viewport==True
360 subrow.itemR(part, "simplify_viewport")
363 elif part.ren_as == 'OBJECT':
364 #sub = split.column()
365 sub.itemR(part, "dupli_object")
366 elif part.ren_as == 'GROUP':
367 sub.itemR(part, "dupli_group")
368 split = layout.split()
370 sub.itemR(part, "whole_group")
372 colsub = sub.column()
373 colsub.active = part.whole_group == False
374 colsub.itemR(part, "rand_group")
376 elif part.ren_as == 'BILLBOARD':
377 sub.itemL(text="Align:")
380 row.itemR(part, "billboard_align", expand=True)
381 row.itemR(part, "billboard_lock", text="Lock")
383 row.itemR(part, "billboard_object")
386 col = row.column(align=True)
387 col.itemL(text="Tilt:")
388 col.itemR(part, "billboard_tilt", text="Angle", slider=True)
389 col.itemR(part, "billboard_random_tilt", slider=True)
391 col.itemR(part, "billboard_offset")
394 row.itemR(psys, "billboard_normal_uv")
396 row.itemR(psys, "billboard_time_index_uv")
399 row.itemL(text="Split uv's:")
400 row.itemR(part, "billboard_uv_split", text="Number of splits")
402 row.itemR(psys, "billboard_split_uv")
404 row.itemL(text="Animate:")
405 row.itemR(part, "billboard_animation", expand=True)
406 row.itemL(text="Offset:")
407 row.itemR(part, "billboard_split_offset", expand=True)
409 class PARTICLE_PT_draw(ParticleButtonsPanel):
410 __idname__= "PARTICLE_PT_draw"
411 __label__ = "Display"
412 __default_closed__ = True
414 def poll(self, context):
415 return (context.particle_system != None)
417 def draw(self, context):
420 psys = context.particle_system
424 row.itemR(part, "draw_as", expand=True)
426 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
429 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
431 if path and part.type!='HAIR' and psys.point_cache.baked==False:
433 box.itemL(text="Baked or keyed particles needed for correct drawing.")
437 row.itemR(part, "display", slider=True)
438 if part.draw_as!='RENDER' or part.ren_as=='HALO':
439 row.itemR(part, "draw_size")
445 col.itemR(part, "show_size")
446 col.itemR(part, "velocity")
447 col.itemR(part, "num")
448 if part.physics_type == 'BOIDS':
449 col.itemR(part, "draw_health")
454 box.itemR(part, "draw_step")
456 col.itemR(part, "material_color", text="Use material color")
457 subcol = col.column()
458 subcol.active = part.material_color==False
459 #subcol.itemL(text="color")
460 #subcol.itemL(text="Override material color")
462 class PARTICLE_PT_children(ParticleButtonsPanel):
463 __idname__= "PARTICLE_PT_children"
464 __label__ = "Children"
465 __default_closed__ = True
467 def draw(self, context):
470 psys = context.particle_system
473 layout.row().itemR(part, "child_type", expand=True)
475 if part.child_type=='NONE':
480 col = row.column(align=True)
481 col.itemR(part, "child_nbr", text="Display")
482 col.itemR(part, "rendered_child_nbr", text="Render")
484 col = row.column(align=True)
486 if part.child_type=='FACES':
487 col.itemR(part, "virtual_parents", slider=True)
489 col.itemR(part, "child_radius", text="Radius")
490 col.itemR(part, "child_roundness", text="Roundness", slider=True)
492 col = row.column(align=True)
493 col.itemR(part, "child_size", text="Size")
494 col.itemR(part, "child_random_size", text="Random")
496 layout.row().itemL(text="Effects:")
500 col = row.column(align=True)
501 col.itemR(part, "clump_factor", slider=True)
502 col.itemR(part, "clumppow", slider=True)
504 col = row.column(align=True)
505 col.itemR(part, "rough_endpoint")
506 col.itemR(part, "rough_end_shape")
510 col = row.column(align=True)
511 col.itemR(part, "rough1")
512 col.itemR(part, "rough1_size")
514 col = row.column(align=True)
515 col.itemR(part, "rough2")
516 col.itemR(part, "rough2_size")
517 col.itemR(part, "rough2_thres", slider=True)
519 layout.row().itemL(text="Kink:")
520 layout.row().itemR(part, "kink", expand=True)
522 split = layout.split()
525 sub.itemR(part, "kink_amplitude")
526 sub.itemR(part, "kink_frequency")
528 sub.itemR(part, "kink_shape", slider=True)
530 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
531 __idname__= "PARTICLE_PT_vertexgroups"
532 __label__ = "Vertexgroups"
533 __default_closed__ = True
535 def draw(self, context):
538 psys = context.particle_system
541 layout.itemL(text="Nothing here yet.")
544 #row.itemL(text="Vertex Group")
545 #row.itemL(text="Negate")
549 #row.itemR(psys, "vertex_group_density")
550 #row.itemR(psys, "vertex_group_density_negate", text="")
553 #row.itemR(psys, "vertex_group_velocity")
554 #row.itemR(psys, "vertex_group_velocity_negate", text="")
557 #row.itemR(psys, "vertex_group_length")
558 #row.itemR(psys, "vertex_group_length_negate", text="")
561 #row.itemR(psys, "vertex_group_clump")
562 #row.itemR(psys, "vertex_group_clump_negate", text="")
565 #row.itemR(psys, "vertex_group_kink")
566 #row.itemR(psys, "vertex_group_kink_negate", text="")
569 #row.itemR(psys, "vertex_group_roughness1")
570 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
573 #row.itemR(psys, "vertex_group_roughness2")
574 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
577 #row.itemR(psys, "vertex_group_roughness_end")
578 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
581 #row.itemR(psys, "vertex_group_size")
582 #row.itemR(psys, "vertex_group_size_negate", text="")
585 #row.itemR(psys, "vertex_group_tangent")
586 #row.itemR(psys, "vertex_group_tangent_negate", text="")
589 #row.itemR(psys, "vertex_group_rotation")
590 #row.itemR(psys, "vertex_group_rotation_negate", text="")
593 #row.itemR(psys, "vertex_group_field")
594 #row.itemR(psys, "vertex_group_field_negate", text="")
596 bpy.types.register(PARTICLE_PT_particles)
597 bpy.types.register(PARTICLE_PT_cache)
598 bpy.types.register(PARTICLE_PT_emission)
599 bpy.types.register(PARTICLE_PT_initial)
600 bpy.types.register(PARTICLE_PT_physics)
601 bpy.types.register(PARTICLE_PT_render)
602 bpy.types.register(PARTICLE_PT_draw)
603 bpy.types.register(PARTICLE_PT_children)
604 bpy.types.register(PARTICLE_PT_vertexgroups)