2.5 Buttons Window:
[blender-staging.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__ = "Particle System"
23
24         def poll(self, context):
25                 return (context.particle_system or context.object)
26
27         def draw(self, context):
28                 layout = self.layout
29                 ob = context.object
30                 psys = context.particle_system
31
32                 split = layout.split(percentage=0.65)
33
34                 if psys:
35                         split.template_ID(context, psys, "settings")
36
37                 if psys:
38                         #row = layout.row()
39                         #row.itemL(text="Viewport")
40                         #row.itemL(text="Render")
41                         
42                         part = psys.settings
43                         ptype = psys.settings.type
44                         
45                         if ptype not in ('EMITTER', 'REACTOR', 'HAIR'):
46                                 layout.itemL(text="No settings for fluid particles")
47                                 return
48                                 
49                         split = layout.split(percentage=0.65)
50                         
51                         split.enabled = particle_panel_enabled(psys)
52                         split.itemR(part, "type")
53                         split.itemR(psys, "seed")
54                         
55                         split = layout.split(percentage=0.65)
56                         if part.type=='HAIR':
57                                 if psys.editable==True:
58                                         split.itemO("PARTICLE_OT_editable_set", text="Free Edit")
59                                 else:
60                                         split.itemO("PARTICLE_OT_editable_set", text="Make Editable")
61                                 row = split.row()
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")
68                 
69 class PARTICLE_PT_emission(ParticleButtonsPanel):
70         __idname__= "PARTICLE_PT_emission"
71         __label__ = "Emission"
72         
73         def draw(self, context):
74                 layout = self.layout
75
76                 psys = context.particle_system
77                 part = psys.settings
78                 
79                 layout.enabled = particle_panel_enabled(psys)
80                 
81                 row = layout.row()
82                 row.itemR(part, "amount")
83                 
84                 split = layout.split()
85                 
86                 col = split.column(align=True)
87                 col.itemR(part, "start")
88                 col.itemR(part, "end")
89
90                 col = split.column(align=True)
91                 col.itemR(part, "lifetime")
92                 col.itemR(part, "random_lifetime", slider=True)
93                 
94                 layout.row().itemL(text="Emit From:")
95                 
96                 row = layout.row()
97                 row.itemR(part, "emit_from", expand=True)
98                 row = layout.row()
99                 row.itemR(part, "trand")
100                 if part.distribution!='GRID':
101                         row.itemR(part, "even_distribution")
102                 
103                 if part.emit_from=='FACE' or part.emit_from=='VOLUME':
104                         row = layout.row()
105                         row.itemR(part, "distribution", expand=True)
106                         
107                         row = layout.row()
108
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")
114
115 class PARTICLE_PT_cache(ParticleButtonsPanel):
116         __idname__= "PARTICLE_PT_cache"
117         __label__ = "Cache"
118         __default_closed__ = True
119         
120         def poll(self, context):
121                 psys = context.particle_system
122                 if psys==None:  return False
123                 return psys.settings.type in ('EMITTER', 'REACTOR')
124
125         def draw(self, context):
126                 layout = self.layout
127
128                 psys = context.particle_system
129                 part = psys.settings
130                 cache = psys.point_cache
131                 
132                 row = layout.row()
133                 row.itemR(cache, "name", text="")
134                 if cache.outdated:
135                         row.itemL(text="Cache is outdated.")
136                 else:
137                         row.itemL(text="")
138                 
139                 row = layout.row()
140                 
141                 if cache.baked == True:
142                         row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
143                 else:
144                         row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
145                         
146                 row = layout.row()
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")
151         
152                 row = layout.row()
153                 row.enabled = particle_panel_enabled(psys)
154                 #row.itemR(cache, "autocache")
155                 row.itemR(cache, "disk_cache")
156                 row.itemL(text=cache.info)
157                 
158                 # for particles these are figured out automatically
159                 #row.itemR(cache, "start_frame")
160                 #row.itemR(cache, "end_frame")
161
162 class PARTICLE_PT_initial(ParticleButtonsPanel):
163         __idname__= "PARTICLE_PT_initial"
164         __label__ = "Velocity"
165
166         def draw(self, context):
167                 layout = self.layout
168
169                 psys = context.particle_system
170                 part = psys.settings
171                 
172                 layout.enabled = particle_panel_enabled(psys)
173                                 
174                 layout.row().itemL(text="Direction:")
175         
176                 split = layout.split()
177                         
178                 sub = split.column()
179                 sub.itemR(part, "normal_factor")
180                 if part.emit_from=='PARTICLE':
181                         sub.itemR(part, "particle_factor")
182                 else:
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)
187                 
188                 sub = split.column()
189                 sub.itemL(text="TODO:")
190                 sub.itemL(text="Object aligned")
191                 sub.itemL(text="direction: X, Y, Z")
192                 
193                 if part.type=='REACTOR':
194                         sub.itemR(part, "reactor_factor")
195                         sub.itemR(part, "reaction_shape", slider=True)
196                 else:
197                         sub.itemL(text="")
198                 
199                 layout.row().itemL(text="Rotation:")
200                 split = layout.split()
201                         
202                 sub = split.column()
203                 
204                 sub.itemR(part, "rotation_mode", text="Axis")
205                 split = layout.split()
206                         
207                 sub = split.column()
208                 sub.itemR(part, "rotation_dynamic")
209                 sub.itemR(part, "random_rotation_factor", slider=True)
210                 sub = split.column()
211                 sub.itemR(part, "phase_factor", slider=True)
212                 sub.itemR(part, "random_phase_factor", text="Random", slider=True)
213
214                 layout.row().itemL(text="Angular velocity:")
215                 layout.row().itemR(part, "angular_velocity_mode", expand=True)
216                 split = layout.split()
217                         
218                 sub = split.column()
219                 
220                 sub.itemR(part, "angular_velocity_factor", text="")
221                 
222 class PARTICLE_PT_physics(ParticleButtonsPanel):
223         __idname__= "PARTICLE_PT_physics"
224         __label__ = "Physics"
225
226         def draw(self, context):
227                 layout = self.layout
228
229                 psys = context.particle_system
230                 part = psys.settings
231                 
232                 layout.enabled = layout.enabled = particle_panel_enabled(psys)
233
234                 row = layout.row()
235                 row.itemR(part, "physics_type", expand=True)
236                 if part.physics_type != 'NO':
237                         layout.itemR(part, "effector_group")
238                 
239                         row = layout.row()
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")
246                                                         
247                         split = layout.split()
248                         
249                         sub = split.column()
250                         
251                 if part.physics_type == 'NEWTON':
252                         
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")
258                         sub = split.column()
259                         sub.itemR(part, "acceleration")
260                         
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")
265                         else:
266                                 sub.itemR(part, "keyed_time")
267                         sub = split.column()
268                         sub.itemL(text="Next key from object:")
269                         sub.itemR(psys, "keyed_object", text="")
270                         sub.itemR(psys, "keyed_particle_system")
271                 
272                 if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
273
274                         sub.itemR(part, "size_deflect")
275                         sub.itemR(part, "die_on_collision")
276                         sub.itemR(part, "sticky")
277
278 class PARTICLE_PT_render(ParticleButtonsPanel):
279         __idname__= "PARTICLE_PT_render"
280         __label__ = "Render"
281         
282         def poll(self, context):
283                 return (context.particle_system != None)
284                 
285         def draw(self, context):
286                 layout = self.layout
287
288                 psys = context.particle_system
289                 part = psys.settings
290                 
291                 layout.itemR(part, "material")
292                 
293                 split = layout.split()
294                         
295                 sub = split.column()
296                 sub.itemR(part, "emitter");
297                 sub.itemR(part, "parent");
298                 sub = split.column()
299                 sub.itemR(part, "unborn");
300                 sub.itemR(part, "died");
301                 
302                 row = layout.row()
303                 row.itemR(part, "ren_as", expand=True)
304                 
305                 split = layout.split()
306                         
307                 sub = split.column()
308                 
309                 if part.ren_as == 'LINE':
310                         sub.itemR(part, "line_length_tail")
311                         sub.itemR(part, "line_length_head")
312                         sub = split.column()
313                         sub.itemR(part, "velocity_length")
314                 elif part.ren_as == 'PATH':
315                 
316                         if (part.type!='HAIR' and psys.point_cache.baked==False):
317                                 box = layout.box()
318                                 box.itemL(text="Baked or keyed particles needed for correct rendering.")
319                                 return
320                                 
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")
333                         sub = split.column()
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)
338                         
339                         #row = layout.row()
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")
345                         
346                         row = layout.row()
347                         col = row.column()
348                         
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:
352                                         row = layout.row()
353                                         row.itemR(part, "simplify_refsize")
354                                         row.itemR(part, "simplify_rate")
355                                         row.itemR(part, "simplify_transition")
356                                         row = layout.row()
357                                         row.itemR(part, "viewport")
358                                         subrow = row.row()
359                                         subrow.active = part.viewport==True
360                                         subrow.itemR(part, "simplify_viewport")
361                         
362
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()
369                         sub = split.column()
370                         sub.itemR(part, "whole_group")
371                         sub = split.column()
372                         colsub = sub.column()
373                         colsub.active = part.whole_group == False
374                         colsub.itemR(part, "rand_group")
375                         
376                 elif part.ren_as == 'BILLBOARD':
377                         sub.itemL(text="Align:")
378                         
379                         row = layout.row()
380                         row.itemR(part, "billboard_align", expand=True)
381                         row.itemR(part, "billboard_lock", text="Lock")
382                         row = layout.row()
383                         row.itemR(part, "billboard_object")
384                 
385                         row = layout.row()
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)
390                         col = row.column()
391                         col.itemR(part, "billboard_offset")
392                         
393                         row = layout.row()
394                         row.itemR(psys, "billboard_normal_uv")
395                         row = layout.row()
396                         row.itemR(psys, "billboard_time_index_uv")
397                         
398                         row = layout.row()
399                         row.itemL(text="Split uv's:")
400                         row.itemR(part, "billboard_uv_split", text="Number of splits")
401                         row = layout.row()
402                         row.itemR(psys, "billboard_split_uv")
403                         row = layout.row()
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)
408                 
409 class PARTICLE_PT_draw(ParticleButtonsPanel):
410         __idname__= "PARTICLE_PT_draw"
411         __label__ = "Display"
412         __default_closed__ = True
413         
414         def poll(self, context):
415                 return (context.particle_system != None)
416         
417         def draw(self, context):
418                 layout = self.layout
419
420                 psys = context.particle_system
421                 part = psys.settings
422                 
423                 row = layout.row()
424                 row.itemR(part, "draw_as", expand=True)
425                 
426                 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
427                         return
428                         
429                 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
430                         
431                 if path and part.type!='HAIR' and psys.point_cache.baked==False:
432                         box = layout.box()
433                         box.itemL(text="Baked or keyed particles needed for correct drawing.")
434                         return
435                 
436                 row = layout.row()
437                 row.itemR(part, "display", slider=True)
438                 if part.draw_as!='RENDER' or part.ren_as=='HALO':
439                         row.itemR(part, "draw_size")
440                 else:
441                         row.itemL(text="")
442                 
443                 row = layout.row()
444                 col = row.column()
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")
450                 
451                 col = row.column()
452                 if (path):
453                         box = col.box()                         
454                         box.itemR(part, "draw_step")
455                 else:
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")
461
462 class PARTICLE_PT_children(ParticleButtonsPanel):
463         __idname__= "PARTICLE_PT_children"
464         __label__ = "Children"
465         __default_closed__ = True
466
467         def draw(self, context):
468                 layout = self.layout
469
470                 psys = context.particle_system
471                 part = psys.settings
472                 
473                 layout.row().itemR(part, "child_type", expand=True)
474                 
475                 if part.child_type=='NONE':
476                         return
477                 
478                 row = layout.row()
479                 
480                 col = row.column(align=True)
481                 col.itemR(part, "child_nbr", text="Display")
482                 col.itemR(part, "rendered_child_nbr", text="Render")
483                 
484                 col = row.column(align=True)
485                 
486                 if part.child_type=='FACES':
487                         col.itemR(part, "virtual_parents", slider=True)
488                 else:
489                         col.itemR(part, "child_radius", text="Radius")
490                         col.itemR(part, "child_roundness", text="Roundness", slider=True)
491                 
492                         col = row.column(align=True)
493                         col.itemR(part, "child_size", text="Size")
494                         col.itemR(part, "child_random_size", text="Random")
495                 
496                 layout.row().itemL(text="Effects:")
497                 
498                 row = layout.row()
499                 
500                 col = row.column(align=True)
501                 col.itemR(part, "clump_factor", slider=True)
502                 col.itemR(part, "clumppow", slider=True)
503                 
504                 col = row.column(align=True)
505                 col.itemR(part, "rough_endpoint")
506                 col.itemR(part, "rough_end_shape")
507
508                 row = layout.row()
509                 
510                 col = row.column(align=True)
511                 col.itemR(part, "rough1")
512                 col.itemR(part, "rough1_size")
513
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)
518                 
519                 layout.row().itemL(text="Kink:")
520                 layout.row().itemR(part, "kink", expand=True)
521                 
522                 split = layout.split()
523                 
524                 sub = split.column()
525                 sub.itemR(part, "kink_amplitude")
526                 sub.itemR(part, "kink_frequency")
527                 sub = split.column()
528                 sub.itemR(part, "kink_shape", slider=True)
529
530 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
531         __idname__= "PARTICLE_PT_vertexgroups"
532         __label__ = "Vertexgroups"
533         __default_closed__ = True
534
535         def draw(self, context):
536                 layout = self.layout
537
538                 psys = context.particle_system
539                 part = psys.settings
540                 
541                 layout.itemL(text="Nothing here yet.")
542
543                 #row = layout.row()
544                 #row.itemL(text="Vertex Group")
545                 #row.itemL(text="Negate")
546
547                 
548                 #row = layout.row()
549                 #row.itemR(psys, "vertex_group_density")
550                 #row.itemR(psys, "vertex_group_density_negate", text="")
551                 
552                 #row = layout.row()
553                 #row.itemR(psys, "vertex_group_velocity")
554                 #row.itemR(psys, "vertex_group_velocity_negate", text="")
555                 
556                 #row = layout.row()
557                 #row.itemR(psys, "vertex_group_length")
558                 #row.itemR(psys, "vertex_group_length_negate", text="")
559                 
560                 #row = layout.row()
561                 #row.itemR(psys, "vertex_group_clump")
562                 #row.itemR(psys, "vertex_group_clump_negate", text="")
563                 
564                 #row = layout.row()
565                 #row.itemR(psys, "vertex_group_kink")
566                 #row.itemR(psys, "vertex_group_kink_negate", text="")
567                 
568                 #row = layout.row()
569                 #row.itemR(psys, "vertex_group_roughness1")
570                 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
571                 
572                 #row = layout.row()
573                 #row.itemR(psys, "vertex_group_roughness2")
574                 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
575                 
576                 #row = layout.row()
577                 #row.itemR(psys, "vertex_group_roughness_end")
578                 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
579
580                 #row = layout.row()
581                 #row.itemR(psys, "vertex_group_size")
582                 #row.itemR(psys, "vertex_group_size_negate", text="")
583                 
584                 #row = layout.row()
585                 #row.itemR(psys, "vertex_group_tangent")
586                 #row.itemR(psys, "vertex_group_tangent_negate", text="")
587                 
588                 #row = layout.row()
589                 #row.itemR(psys, "vertex_group_rotation")
590                 #row.itemR(psys, "vertex_group_rotation_negate", text="")
591                 
592                 #row = layout.row()
593                 #row.itemR(psys, "vertex_group_field")
594                 #row.itemR(psys, "vertex_group_field_negate", text="")
595                 
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)