2.5 Interface:
[blender.git] / release / ui / buttons_particle.py
1
2 import bpy
3
4 def particle_panel_enabled(psys):
5         return psys.point_cache.baked==False and psys.editable==False
6         
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')
11
12 class ParticleButtonsPanel(bpy.types.Panel):
13         __space_type__ = "BUTTONS_WINDOW"
14         __region_type__ = "WINDOW"
15         __context__ = "particle"
16
17         def poll(self, context):
18                 return particle_panel_poll(context)
19
20 class PARTICLE_PT_particles(ParticleButtonsPanel):
21         __idname__= "PARTICLE_PT_particles"
22         __label__ = "ParticleSystem"
23
24         def poll(self, context):
25                 return (context.particle_system != None)
26         
27         def draw(self, context):
28                 layout = self.layout
29
30                 psys = context.particle_system
31                 part = psys.settings
32                 
33                 #row = layout.row()
34                 #row.itemL(text="Particle system datablock")
35                 #row.itemL(text="Viewport")
36                 #row.itemL(text="Render")
37                 
38                 ptype = psys.settings.type
39                 
40                 if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
41                         layout.itemL(text="No settings for fluid particles")
42                         return
43                 
44                 row = layout.row()
45                 row.enabled = particle_panel_enabled(psys)
46                 row.itemR(part, "type", expand=True)
47                 
48                 
49                 row = layout.row()
50                 if part.type=='HAIR':
51                         if psys.editable==True:
52                                 row.itemO("PARTICLE_OT_editable_set", text="Free Edit")
53                         else:
54                                 row.itemO("PARTICLE_OT_editable_set", text="Make Editable")
55                         subrow = row.row()
56                         subrow.enabled = particle_panel_enabled(psys)
57                         subrow.itemR(part, "hair_step")
58                 elif part.type=='REACTOR':
59                         row.itemR(psys, "reactor_target_object")
60                         row.itemR(psys, "reactor_target_particle_system", text="Particle System")
61                 
62 class PARTICLE_PT_emission(ParticleButtonsPanel):
63         __idname__= "PARTICLE_PT_emission"
64         __label__ = "Emission"
65         
66         def draw(self, context):
67                 layout = self.layout
68
69                 psys = context.particle_system
70                 part = psys.settings
71                 
72                 layout.enabled = particle_panel_enabled(psys)
73                 
74                 row = layout.row()
75                 #col.itemL(text="TODO: Rate instead of amount")
76                 row.itemR(part, "amount")
77                 row.itemR(psys, "seed")
78                 
79                 split = layout.split()
80                 
81                 col = split.column(align=True)
82                 col.itemR(part, "start")
83                 col.itemR(part, "end")
84
85                 col = split.column(align=True)
86                 col.itemR(part, "lifetime")
87                 col.itemR(part, "random_lifetime", slider=True)
88                 
89                 layout.row().itemL(text="Emit From:")
90                 
91                 row = layout.row()
92                 row.itemR(part, "emit_from", expand=True)
93                 row = layout.row()
94                 row.itemR(part, "trand")
95                 if part.distribution!='GRID':
96                         row.itemR(part, "even_distribution")
97                 
98                 if part.emit_from=='FACE' or part.emit_from=='VOLUME':
99                         row = layout.row()
100                         row.itemR(part, "distribution", expand=True)
101                         
102                         row = layout.row()
103
104                         if part.distribution=='JIT':
105                                 row.itemR(part, "userjit", text="Particles/Face")
106                                 row.itemR(part, "jitter_factor", text="Jittering Amount", slider=True)
107                         elif part.distribution=='GRID':
108                                 row.itemR(part, "grid_resolution")
109
110 class PARTICLE_PT_cache(ParticleButtonsPanel):
111         __idname__= "PARTICLE_PT_cache"
112         __label__ = "Cache"
113         
114         def poll(self, context):
115                 psys = context.particle_system
116                 if psys==None:  return False
117                 return psys.settings.type in ('EMITTER', 'REACTOR')
118
119         def draw(self, context):
120                 layout = self.layout
121
122                 psys = context.particle_system
123                 part = psys.settings
124                 cache = psys.point_cache
125                 
126                 #if cache.baked==True:
127                         #layout.itemO("PARTICLE_OT_free_bake", text="BAKE")
128                 #else:
129                 row = layout.row()
130                         #row.itemO("PARTICLE_OT_bake", text="BAKE")
131                 row.itemR(cache, "start_frame")
132                 row.itemR(cache, "end_frame")
133                         
134                         #layout.row().itemL(text="No simulation frames in disk cache.")
135
136 class PARTICLE_PT_initial(ParticleButtonsPanel):
137         __idname__= "PARTICLE_PT_initial"
138         __label__ = "Velocity"
139
140         def draw(self, context):
141                 layout = self.layout
142
143                 psys = context.particle_system
144                 part = psys.settings
145                 
146                 layout.enabled = particle_panel_enabled(psys)
147                 
148                 #layout.row().itemL(text="")
149                                 
150                 layout.row().itemL(text="Direction:")
151         
152                 split = layout.split()
153                         
154                 sub = split.column()
155                 sub.itemR(part, "normal_factor")
156                 if part.emit_from=='PARTICLE':
157                         sub.itemR(part, "particle_factor")
158                 else:
159                         sub.itemR(part, "object_factor", slider=True)
160                 sub.itemR(part, "random_factor")
161                 sub.itemR(part, "tangent_factor")
162                 sub.itemR(part, "tangent_phase", slider=True)
163                 
164                 sub = split.column()
165                 sub.itemL(text="TODO:")
166                 sub.itemL(text="Object aligned")
167                 sub.itemL(text="direction: X, Y, Z")
168                 
169                 if part.type=='REACTOR':
170                         sub.itemR(part, "reactor_factor")
171                         sub.itemR(part, "reaction_shape", slider=True)
172                 else:
173                         sub.itemL(text="")
174                 
175                 layout.row().itemL(text="Rotation:")
176                 split = layout.split()
177                         
178                 sub = split.column()
179                 
180                 sub.itemR(part, "rotation_mode", text="Axis")
181                 split = layout.split()
182                         
183                 sub = split.column()
184                 sub.itemR(part, "rotation_dynamic")
185                 sub.itemR(part, "random_rotation_factor", slider=True)
186                 sub = split.column()
187                 sub.itemR(part, "phase_factor", slider=True)
188                 sub.itemR(part, "random_phase_factor", text="Random", slider=True)
189
190                 layout.row().itemL(text="Angular velocity:")
191                 layout.row().itemR(part, "angular_velocity_mode", expand=True)
192                 split = layout.split()
193                         
194                 sub = split.column()
195                 
196                 sub.itemR(part, "angular_velocity_factor", text="")
197                 
198 class PARTICLE_PT_physics(ParticleButtonsPanel):
199         __idname__= "PARTICLE_PT_physics"
200         __label__ = "Physics"
201
202         def draw(self, context):
203                 layout = self.layout
204
205                 psys = context.particle_system
206                 part = psys.settings
207                 
208                 layout.enabled = layout.enabled = particle_panel_enabled(psys)
209
210                 row = layout.row()
211                 row.itemR(part, "physics_type", expand=True)
212                 if part.physics_type != 'NO':
213                         layout.itemR(part, "effector_group")
214                 
215                         row = layout.row()
216                         col = row.column(align=True)
217                         col.itemR(part, "particle_size")
218                         col.itemR(part, "random_size", slider=True)
219                         col = row.column(align=True)
220                         col.itemR(part, "mass")
221                         col.itemR(part, "sizemass", text="Multiply mass with size")
222                                                         
223                         split = layout.split()
224                         
225                         sub = split.column()
226                         
227                 if part.physics_type == 'NEWTON':
228                         
229                         sub.itemL(text="Forces:")
230                         sub.itemR(part, "brownian_factor")
231                         sub.itemR(part, "drag_factor", slider=True)
232                         sub.itemR(part, "damp_factor", slider=True)
233                         sub.itemR(part, "integrator")
234                         sub = split.column()
235                         sub.itemR(part, "acceleration")
236                         
237                 elif part.physics_type == 'KEYED':
238                         sub.itemR(psys, "keyed_first")
239                         if psys.keyed_first==True:
240                                 sub.itemR(psys, "timed_keys", text="Key timing")
241                         else:
242                                 sub.itemR(part, "keyed_time")
243                         sub = split.column()
244                         sub.itemL(text="Next key from object:")
245                         sub.itemR(psys, "keyed_object", text="")
246                         sub.itemR(psys, "keyed_particle_system")
247                 
248                 if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
249
250                         sub.itemR(part, "size_deflect")
251                         sub.itemR(part, "die_on_collision")
252                         sub.itemR(part, "sticky")
253
254 class PARTICLE_PT_render(ParticleButtonsPanel):
255         __idname__= "PARTICLE_PT_render"
256         __label__ = "Render"
257         
258         def poll(self, context):
259                 return (context.particle_system != None)
260                 
261         def draw(self, context):
262                 layout = self.layout
263
264                 psys = context.particle_system
265                 part = psys.settings
266                 
267                 layout.itemR(part, "material")
268                 
269                 split = layout.split()
270                         
271                 sub = split.column()
272                 sub.itemR(part, "emitter");
273                 sub.itemR(part, "parent");
274                 sub = split.column()
275                 sub.itemR(part, "unborn");
276                 sub.itemR(part, "died");
277                 
278                 row = layout.row()
279                 row.itemR(part, "ren_as", expand=True)
280                 
281                 split = layout.split()
282                         
283                 sub = split.column()
284                 
285                 if part.ren_as == 'LINE':
286                         sub.itemR(part, "line_length_tail")
287                         sub.itemR(part, "line_length_head")
288                         sub = split.column()
289                         sub.itemR(part, "velocity_length")
290                 elif part.ren_as == 'PATH':
291                 
292                         if (part.type!='HAIR' and psys.point_cache.baked==False):
293                                 box = layout.box()
294                                 box.itemL(text="Baked or keyed particles needed for correct rendering.")
295                                 return
296                                 
297                         sub.itemR(part, "render_strand")
298                         colsub = sub.column()
299                         colsub.active = part.render_strand == False
300                         colsub.itemR(part, "render_adaptive")
301                         colsub = sub.column()
302                         colsub.active = part.render_adaptive or part.render_strand == True
303                         colsub.itemR(part, "adaptive_angle")
304                         colsub = sub.column()
305                         colsub.active = part.render_adaptive == True and part.render_strand == False
306                         colsub.itemR(part, "adaptive_pix")
307                         sub.itemR(part, "hair_bspline")
308                         sub.itemR(part, "render_step", text="Steps")
309                         sub = split.column()
310                         sub.itemL(text="Length:")
311                         sub.itemR(part, "abs_length", text="Absolute")
312                         sub.itemR(part, "absolute_length", text="Maximum")
313                         sub.itemR(part, "random_length", text="Random", slider=True)
314                         
315                         #row = layout.row()
316                         #row.itemR(part, "timed_path")
317                         #col = row.column(align=True)
318                         #col.active = part.timed_path == True
319                         #col.itemR(part, "line_length_tail", text="Start")
320                         #col.itemR(part, "line_length_head", text="End")
321                         
322                         row = layout.row()
323                         col = row.column()
324                         
325                         
326 #                       subrow = col.row()
327 #                       subrow.active = part.render_strand == False
328 #                       subrow.itemR(part, "render_adaptive")
329 #                       col = row.column(align=True)
330 #                       subrow = col.row()
331 #                       subrow.active = part.render_adaptive or part.render_strand == True
332 #                       subrow.itemR(part, "adaptive_angle")
333 #                       subrow = col.row()
334 #                       subrow.active = part.render_adaptive == True and part.render_strand == False
335 #                       subrow.itemR(part, "adaptive_pix")
336                         
337                         if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
338                                 layout.itemR(part, "enable_simplify")
339                                 if part.enable_simplify==True:
340                                         box = layout.box()
341                                         row = box.row()
342                                         row.itemR(part, "simplify_refsize")
343                                         row.itemR(part, "simplify_rate")
344                                         row.itemR(part, "simplify_transition")
345                                         row = box.row()
346                                         row.itemR(part, "viewport")
347                                         subrow = row.row()
348                                         subrow.active = part.viewport==True
349                                         subrow.itemR(part, "simplify_viewport")
350                         
351
352                 elif part.ren_as == 'OBJECT':
353                         #sub = split.column()
354                         sub.itemR(part, "dupli_object")
355                 elif part.ren_as == 'GROUP':
356                         sub.itemR(part, "dupli_group")
357                         split = layout.split()
358                         sub = split.column()
359                         sub.itemR(part, "whole_group")
360                         sub = split.column()
361                         colsub = sub.column()
362                         colsub.active = part.whole_group == False
363                         colsub.itemR(part, "rand_group")
364                         
365                 elif part.ren_as == 'BILLBOARD':
366                         sub.itemL(text="Align:")
367                         
368                         row = layout.row()
369                         row.itemR(part, "billboard_align", expand=True)
370                         row.itemR(part, "billboard_lock", text="Lock")
371                         row = layout.row()
372                         row.itemR(part, "billboard_object")
373                 
374                         row = layout.row()
375                         col = row.column(align=True)
376                         col.itemL(text="Tilt:")
377                         col.itemR(part, "billboard_tilt", text="Angle", slider=True)
378                         col.itemR(part, "billboard_random_tilt", slider=True)
379                         col = row.column()
380                         col.itemR(part, "billboard_offset")
381                         
382                         row = layout.row()
383                         row.itemR(psys, "billboard_normal_uv")
384                         row = layout.row()
385                         row.itemR(psys, "billboard_time_index_uv")
386                         
387                         row = layout.row()
388                         row.itemL(text="Split uv's:")
389                         row.itemR(part, "billboard_uv_split", text="Number of splits")
390                         row = layout.row()
391                         row.itemR(psys, "billboard_split_uv")
392                         row = layout.row()
393                         row.itemL(text="Animate:")
394                         row.itemR(part, "billboard_animation", expand=True)
395                         row.itemL(text="Offset:")
396                         row.itemR(part, "billboard_split_offset", expand=True)
397                 
398 class PARTICLE_PT_draw(ParticleButtonsPanel):
399         __idname__= "PARTICLE_PT_draw"
400         __label__ = "Display"
401         
402         def poll(self, context):
403                 return (context.particle_system != None)
404         
405         def draw(self, context):
406                 layout = self.layout
407
408                 psys = context.particle_system
409                 part = psys.settings
410                 
411                 row = layout.row()
412                 row.itemR(part, "draw_as", expand=True)
413                 
414                 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
415                         return
416                         
417                 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
418                         
419                 if path and part.type!='HAIR' and psys.point_cache.baked==False:
420                         box = layout.box()
421                         box.itemL(text="Baked or keyed particles needed for correct drawing.")
422                         return
423                 
424                 row = layout.row()
425                 row.itemR(part, "display", slider=True)
426                 if part.draw_as!='RENDER' or part.ren_as=='HALO':
427                         row.itemR(part, "draw_size")
428                 else:
429                         row.itemL(text="")
430                 
431                 row = layout.row()
432                 col = row.column()
433                 col.itemR(part, "show_size")
434                 col.itemR(part, "velocity")
435                 col.itemR(part, "num")
436                 if part.physics_type == 'BOIDS':
437                         col.itemR(part, "draw_health")
438                 
439                 col = row.column()
440                 if (path):
441                         box = col.box()                         
442                         box.itemR(part, "draw_step")
443                 else:
444                         col.itemR(part, "material_color", text="Use material color")
445                         subcol = col.column()
446                         subcol.active = part.material_color==False
447                         #subcol.itemL(text="color")
448                         #subcol.itemL(text="Override material color")
449
450 class PARTICLE_PT_children(ParticleButtonsPanel):
451         __idname__= "PARTICLE_PT_children"
452         __label__ = "Children"
453
454         def draw(self, context):
455                 layout = self.layout
456
457                 psys = context.particle_system
458                 part = psys.settings
459                 
460                 layout.row().itemR(part, "child_type", expand=True)
461                 
462                 if part.child_type=='NONE':
463                         return
464                 
465                 row = layout.row()
466                 
467                 col = row.column(align=True)
468                 col.itemR(part, "child_nbr", text="Display")
469                 col.itemR(part, "rendered_child_nbr", text="Render")
470                 
471                 col = row.column(align=True)
472                 
473                 if part.child_type=='FACES':
474                         col.itemR(part, "virtual_parents", slider=True)
475                 else:
476                         col.itemR(part, "child_radius", text="Radius")
477                         col.itemR(part, "child_roundness", text="Roundness", slider=True)
478                 
479                         col = row.column(align=True)
480                         col.itemR(part, "child_size", text="Size")
481                         col.itemR(part, "child_random_size", text="Random")
482                 
483                 layout.row().itemL(text="Effects:")
484                 
485                 row = layout.row()
486                 
487                 col = row.column(align=True)
488                 col.itemR(part, "clump_factor", slider=True)
489                 col.itemR(part, "clumppow", slider=True)
490                 
491                 col = row.column(align=True)
492                 col.itemR(part, "rough_endpoint")
493                 col.itemR(part, "rough_end_shape")
494
495                 row = layout.row()
496                 
497                 col = row.column(align=True)
498                 col.itemR(part, "rough1")
499                 col.itemR(part, "rough1_size")
500
501                 col = row.column(align=True)
502                 col.itemR(part, "rough2")
503                 col.itemR(part, "rough2_size")
504                 col.itemR(part, "rough2_thres", slider=True)
505                 
506                 layout.row().itemL(text="Kink:")
507                 layout.row().itemR(part, "kink", expand=True)
508                 
509                 split = layout.split()
510                 
511                 sub = split.column()
512                 sub.itemR(part, "kink_amplitude")
513                 sub.itemR(part, "kink_frequency")
514                 sub = split.column()
515                 sub.itemR(part, "kink_shape", slider=True)
516
517 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
518         __idname__= "PARTICLE_PT_vertexgroups"
519         __label__ = "Vertexgroups"
520
521         def draw(self, context):
522                 layout = self.layout
523
524                 psys = context.particle_system
525                 part = psys.settings
526                 
527                 layout.itemL(text="Nothing here yet.")
528
529                 #row = layout.row()
530                 #row.itemL(text="Vertex Group")
531                 #row.itemL(text="Negate")
532
533                 
534                 #row = layout.row()
535                 #row.itemR(psys, "vertex_group_density")
536                 #row.itemR(psys, "vertex_group_density_negate", text="")
537                 
538                 #row = layout.row()
539                 #row.itemR(psys, "vertex_group_velocity")
540                 #row.itemR(psys, "vertex_group_velocity_negate", text="")
541                 
542                 #row = layout.row()
543                 #row.itemR(psys, "vertex_group_length")
544                 #row.itemR(psys, "vertex_group_length_negate", text="")
545                 
546                 #row = layout.row()
547                 #row.itemR(psys, "vertex_group_clump")
548                 #row.itemR(psys, "vertex_group_clump_negate", text="")
549                 
550                 #row = layout.row()
551                 #row.itemR(psys, "vertex_group_kink")
552                 #row.itemR(psys, "vertex_group_kink_negate", text="")
553                 
554                 #row = layout.row()
555                 #row.itemR(psys, "vertex_group_roughness1")
556                 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
557                 
558                 #row = layout.row()
559                 #row.itemR(psys, "vertex_group_roughness2")
560                 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
561                 
562                 #row = layout.row()
563                 #row.itemR(psys, "vertex_group_roughness_end")
564                 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
565
566                 #row = layout.row()
567                 #row.itemR(psys, "vertex_group_size")
568                 #row.itemR(psys, "vertex_group_size_negate", text="")
569                 
570                 #row = layout.row()
571                 #row.itemR(psys, "vertex_group_tangent")
572                 #row.itemR(psys, "vertex_group_tangent_negate", text="")
573                 
574                 #row = layout.row()
575                 #row.itemR(psys, "vertex_group_rotation")
576                 #row.itemR(psys, "vertex_group_rotation_negate", text="")
577                 
578                 #row = layout.row()
579                 #row.itemR(psys, "vertex_group_field")
580                 #row.itemR(psys, "vertex_group_field_negate", text="")
581                 
582 bpy.types.register(PARTICLE_PT_particles)
583 bpy.types.register(PARTICLE_PT_cache)
584 bpy.types.register(PARTICLE_PT_emission)
585 bpy.types.register(PARTICLE_PT_initial)
586 bpy.types.register(PARTICLE_PT_physics)
587 bpy.types.register(PARTICLE_PT_render)
588 bpy.types.register(PARTICLE_PT_draw)
589 bpy.types.register(PARTICLE_PT_children)
590 bpy.types.register(PARTICLE_PT_vertexgroups)