378689e820289bf6c74fee73497d16a4afbd722e
[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(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")
134                 
135                 row = layout.row()
136                 
137                 if cache.baked == True:
138                         row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
139                 else:
140                         row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
141                 
142                 subrow = row.row()
143                 subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
144                 subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
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                 row.itemR(cache, "step");
150         
151                 row = layout.row()
152                 row.enabled = particle_panel_enabled(psys)
153                 row.itemR(cache, "quick_cache")
154                 row.itemR(cache, "disk_cache")
155                 
156                 layout.itemL(text=cache.info)
157                 
158                 layout.itemS()
159                 
160                 row = layout.row()
161                 row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
162                 row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
163                 layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
164                 
165                 # for particles these are figured out automatically
166                 #row.itemR(cache, "start_frame")
167                 #row.itemR(cache, "end_frame")
168
169 class PARTICLE_PT_initial(ParticleButtonsPanel):
170         __idname__= "PARTICLE_PT_initial"
171         __label__ = "Velocity"
172
173         def draw(self, context):
174                 layout = self.layout
175
176                 psys = context.particle_system
177                 part = psys.settings
178                 
179                 layout.enabled = particle_panel_enabled(psys)
180                                 
181                 layout.row().itemL(text="Direction:")
182         
183                 split = layout.split()
184                         
185                 sub = split.column()
186                 sub.itemR(part, "normal_factor")
187                 if part.emit_from=='PARTICLE':
188                         sub.itemR(part, "particle_factor")
189                 else:
190                         sub.itemR(part, "object_factor", slider=True)
191                 sub.itemR(part, "random_factor")
192                 sub.itemR(part, "tangent_factor")
193                 sub.itemR(part, "tangent_phase", slider=True)
194                 
195                 sub = split.column()
196                 sub.itemL(text="TODO:")
197                 sub.itemL(text="Object aligned")
198                 sub.itemL(text="direction: X, Y, Z")
199                 
200                 if part.type=='REACTOR':
201                         sub.itemR(part, "reactor_factor")
202                         sub.itemR(part, "reaction_shape", slider=True)
203                 else:
204                         sub.itemL(text="")
205                 
206                 layout.row().itemL(text="Rotation:")
207                 split = layout.split()
208                         
209                 sub = split.column()
210                 
211                 sub.itemR(part, "rotation_mode", text="Axis")
212                 split = layout.split()
213                         
214                 sub = split.column()
215                 sub.itemR(part, "rotation_dynamic")
216                 sub.itemR(part, "random_rotation_factor", slider=True)
217                 sub = split.column()
218                 sub.itemR(part, "phase_factor", slider=True)
219                 sub.itemR(part, "random_phase_factor", text="Random", slider=True)
220
221                 layout.row().itemL(text="Angular velocity:")
222                 layout.row().itemR(part, "angular_velocity_mode", expand=True)
223                 split = layout.split()
224                         
225                 sub = split.column()
226                 
227                 sub.itemR(part, "angular_velocity_factor", text="")
228                 
229 class PARTICLE_PT_physics(ParticleButtonsPanel):
230         __idname__= "PARTICLE_PT_physics"
231         __label__ = "Physics"
232
233         def draw(self, context):
234                 layout = self.layout
235
236                 psys = context.particle_system
237                 part = psys.settings
238                 
239                 layout.enabled = layout.enabled = particle_panel_enabled(psys)
240
241                 row = layout.row()
242                 row.itemR(part, "physics_type", expand=True)
243                 if part.physics_type != 'NO':
244                         layout.itemR(part, "effector_group")
245                 
246                         row = layout.row()
247                         col = row.column(align=True)
248                         col.itemR(part, "particle_size")
249                         col.itemR(part, "random_size", slider=True)
250                         col = row.column(align=True)
251                         col.itemR(part, "mass")
252                         col.itemR(part, "sizemass", text="Multiply mass with size")
253                                                         
254                         split = layout.split()
255                         
256                         sub = split.column()
257                         
258                 if part.physics_type == 'NEWTON':
259                         
260                         sub.itemL(text="Forces:")
261                         sub.itemR(part, "brownian_factor")
262                         sub.itemR(part, "drag_factor", slider=True)
263                         sub.itemR(part, "damp_factor", slider=True)
264                         sub.itemR(part, "integrator")
265                         sub = split.column()
266                         sub.itemR(part, "acceleration")
267                         
268                 elif part.physics_type == 'KEYED':
269                         sub.itemR(psys, "keyed_first")
270                         if psys.keyed_first==True:
271                                 sub.itemR(psys, "timed_keys", text="Key timing")
272                         else:
273                                 sub.itemR(part, "keyed_time")
274                         sub = split.column()
275                         sub.itemL(text="Next key from object:")
276                         sub.itemR(psys, "keyed_object", text="")
277                         sub.itemR(psys, "keyed_particle_system")
278                 
279                 if part.physics_type=='NEWTON' or part.physics_type=='BOIDS':
280
281                         sub.itemR(part, "size_deflect")
282                         sub.itemR(part, "die_on_collision")
283                         sub.itemR(part, "sticky")
284
285 class PARTICLE_PT_render(ParticleButtonsPanel):
286         __idname__= "PARTICLE_PT_render"
287         __label__ = "Render"
288         
289         def poll(self, context):
290                 return (context.particle_system != None)
291                 
292         def draw(self, context):
293                 layout = self.layout
294
295                 psys = context.particle_system
296                 part = psys.settings
297                 
298                 row = layout.row()
299                 row.itemR(part, "material")
300                 row.itemR(psys, "parent");
301                 
302                 split = layout.split()
303                         
304                 sub = split.column()
305                 sub.itemR(part, "emitter");
306                 sub.itemR(part, "parent");
307                 sub = split.column()
308                 sub.itemR(part, "unborn");
309                 sub.itemR(part, "died");
310                 
311                 row = layout.row()
312                 row.itemR(part, "ren_as", expand=True)
313                 
314                 split = layout.split()
315                         
316                 sub = split.column()
317                 
318                 if part.ren_as == 'LINE':
319                         sub.itemR(part, "line_length_tail")
320                         sub.itemR(part, "line_length_head")
321                         sub = split.column()
322                         sub.itemR(part, "velocity_length")
323                 elif part.ren_as == 'PATH':
324                 
325                         if (part.type!='HAIR' and psys.point_cache.baked==False):
326                                 box = layout.box()
327                                 box.itemL(text="Baked or keyed particles needed for correct rendering.")
328                                 return
329                                 
330                         sub.itemR(part, "render_strand")
331                         colsub = sub.column()
332                         colsub.active = part.render_strand == False
333                         colsub.itemR(part, "render_adaptive")
334                         colsub = sub.column()
335                         colsub.active = part.render_adaptive or part.render_strand == True
336                         colsub.itemR(part, "adaptive_angle")
337                         colsub = sub.column()
338                         colsub.active = part.render_adaptive == True and part.render_strand == False
339                         colsub.itemR(part, "adaptive_pix")
340                         sub.itemR(part, "hair_bspline")
341                         sub.itemR(part, "render_step", text="Steps")
342                         sub = split.column()
343                         sub.itemL(text="Length:")
344                         sub.itemR(part, "abs_length", text="Absolute")
345                         sub.itemR(part, "absolute_length", text="Maximum")
346                         sub.itemR(part, "random_length", text="Random", slider=True)
347                         
348                         #row = layout.row()
349                         #row.itemR(part, "timed_path")
350                         #col = row.column(align=True)
351                         #col.active = part.timed_path == True
352                         #col.itemR(part, "line_length_tail", text="Start")
353                         #col.itemR(part, "line_length_head", text="End")
354                         
355                         row = layout.row()
356                         col = row.column()
357                         
358                         if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
359                                 layout.itemR(part, "enable_simplify")
360                                 if part.enable_simplify==True:
361                                         row = layout.row()
362                                         row.itemR(part, "simplify_refsize")
363                                         row.itemR(part, "simplify_rate")
364                                         row.itemR(part, "simplify_transition")
365                                         row = layout.row()
366                                         row.itemR(part, "viewport")
367                                         subrow = row.row()
368                                         subrow.active = part.viewport==True
369                                         subrow.itemR(part, "simplify_viewport")
370                         
371
372                 elif part.ren_as == 'OBJECT':
373                         #sub = split.column()
374                         sub.itemR(part, "dupli_object")
375                 elif part.ren_as == 'GROUP':
376                         sub.itemR(part, "dupli_group")
377                         split = layout.split()
378                         sub = split.column()
379                         sub.itemR(part, "whole_group")
380                         sub = split.column()
381                         colsub = sub.column()
382                         colsub.active = part.whole_group == False
383                         colsub.itemR(part, "rand_group")
384                         
385                 elif part.ren_as == 'BILLBOARD':
386                         sub.itemL(text="Align:")
387                         
388                         row = layout.row()
389                         row.itemR(part, "billboard_align", expand=True)
390                         row.itemR(part, "billboard_lock", text="Lock")
391                         row = layout.row()
392                         row.itemR(part, "billboard_object")
393                 
394                         row = layout.row()
395                         col = row.column(align=True)
396                         col.itemL(text="Tilt:")
397                         col.itemR(part, "billboard_tilt", text="Angle", slider=True)
398                         col.itemR(part, "billboard_random_tilt", slider=True)
399                         col = row.column()
400                         col.itemR(part, "billboard_offset")
401                         
402                         row = layout.row()
403                         row.itemR(psys, "billboard_normal_uv")
404                         row = layout.row()
405                         row.itemR(psys, "billboard_time_index_uv")
406                         
407                         row = layout.row()
408                         row.itemL(text="Split uv's:")
409                         row.itemR(part, "billboard_uv_split", text="Number of splits")
410                         row = layout.row()
411                         row.itemR(psys, "billboard_split_uv")
412                         row = layout.row()
413                         row.itemL(text="Animate:")
414                         row.itemR(part, "billboard_animation", expand=True)
415                         row.itemL(text="Offset:")
416                         row.itemR(part, "billboard_split_offset", expand=True)
417                 
418 class PARTICLE_PT_draw(ParticleButtonsPanel):
419         __idname__= "PARTICLE_PT_draw"
420         __label__ = "Display"
421         __default_closed__ = True
422         
423         def poll(self, context):
424                 return (context.particle_system != None)
425         
426         def draw(self, context):
427                 layout = self.layout
428
429                 psys = context.particle_system
430                 part = psys.settings
431                 
432                 row = layout.row()
433                 row.itemR(part, "draw_as", expand=True)
434                 
435                 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
436                         return
437                         
438                 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
439                         
440                 if path and part.type!='HAIR' and psys.point_cache.baked==False:
441                         box = layout.box()
442                         box.itemL(text="Baked or keyed particles needed for correct drawing.")
443                         return
444                 
445                 row = layout.row()
446                 row.itemR(part, "display", slider=True)
447                 if part.draw_as!='RENDER' or part.ren_as=='HALO':
448                         row.itemR(part, "draw_size")
449                 else:
450                         row.itemL(text="")
451                 
452                 row = layout.row()
453                 col = row.column()
454                 col.itemR(part, "show_size")
455                 col.itemR(part, "velocity")
456                 col.itemR(part, "num")
457                 if part.physics_type == 'BOIDS':
458                         col.itemR(part, "draw_health")
459                 
460                 col = row.column()
461                 if (path):
462                         box = col.box()                         
463                         box.itemR(part, "draw_step")
464                 else:
465                         col.itemR(part, "material_color", text="Use material color")
466                         subcol = col.column()
467                         subcol.active = part.material_color==False
468                         #subcol.itemL(text="color")
469                         #subcol.itemL(text="Override material color")
470
471 class PARTICLE_PT_children(ParticleButtonsPanel):
472         __idname__= "PARTICLE_PT_children"
473         __label__ = "Children"
474         __default_closed__ = True
475
476         def draw(self, context):
477                 layout = self.layout
478
479                 psys = context.particle_system
480                 part = psys.settings
481                 
482                 layout.row().itemR(part, "child_type", expand=True)
483                 
484                 if part.child_type=='NONE':
485                         return
486                 
487                 row = layout.row()
488                 
489                 col = row.column(align=True)
490                 col.itemR(part, "child_nbr", text="Display")
491                 col.itemR(part, "rendered_child_nbr", text="Render")
492                 
493                 col = row.column(align=True)
494                 
495                 if part.child_type=='FACES':
496                         col.itemR(part, "virtual_parents", slider=True)
497                 else:
498                         col.itemR(part, "child_radius", text="Radius")
499                         col.itemR(part, "child_roundness", text="Roundness", slider=True)
500                 
501                         col = row.column(align=True)
502                         col.itemR(part, "child_size", text="Size")
503                         col.itemR(part, "child_random_size", text="Random")
504                 
505                 layout.row().itemL(text="Effects:")
506                 
507                 row = layout.row()
508                 
509                 col = row.column(align=True)
510                 col.itemR(part, "clump_factor", slider=True)
511                 col.itemR(part, "clumppow", slider=True)
512                 
513                 col = row.column(align=True)
514                 col.itemR(part, "rough_endpoint")
515                 col.itemR(part, "rough_end_shape")
516
517                 row = layout.row()
518                 
519                 col = row.column(align=True)
520                 col.itemR(part, "rough1")
521                 col.itemR(part, "rough1_size")
522
523                 col = row.column(align=True)
524                 col.itemR(part, "rough2")
525                 col.itemR(part, "rough2_size")
526                 col.itemR(part, "rough2_thres", slider=True)
527                 
528                 layout.row().itemL(text="Kink:")
529                 layout.row().itemR(part, "kink", expand=True)
530                 
531                 split = layout.split()
532                 
533                 sub = split.column()
534                 sub.itemR(part, "kink_amplitude")
535                 sub.itemR(part, "kink_frequency")
536                 sub = split.column()
537                 sub.itemR(part, "kink_shape", slider=True)
538
539 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
540         __idname__= "PARTICLE_PT_vertexgroups"
541         __label__ = "Vertexgroups"
542         __default_closed__ = True
543
544         def draw(self, context):
545                 layout = self.layout
546
547                 psys = context.particle_system
548                 part = psys.settings
549                 
550                 layout.itemL(text="Nothing here yet.")
551
552                 #row = layout.row()
553                 #row.itemL(text="Vertex Group")
554                 #row.itemL(text="Negate")
555
556                 
557                 #row = layout.row()
558                 #row.itemR(psys, "vertex_group_density")
559                 #row.itemR(psys, "vertex_group_density_negate", text="")
560                 
561                 #row = layout.row()
562                 #row.itemR(psys, "vertex_group_velocity")
563                 #row.itemR(psys, "vertex_group_velocity_negate", text="")
564                 
565                 #row = layout.row()
566                 #row.itemR(psys, "vertex_group_length")
567                 #row.itemR(psys, "vertex_group_length_negate", text="")
568                 
569                 #row = layout.row()
570                 #row.itemR(psys, "vertex_group_clump")
571                 #row.itemR(psys, "vertex_group_clump_negate", text="")
572                 
573                 #row = layout.row()
574                 #row.itemR(psys, "vertex_group_kink")
575                 #row.itemR(psys, "vertex_group_kink_negate", text="")
576                 
577                 #row = layout.row()
578                 #row.itemR(psys, "vertex_group_roughness1")
579                 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
580                 
581                 #row = layout.row()
582                 #row.itemR(psys, "vertex_group_roughness2")
583                 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
584                 
585                 #row = layout.row()
586                 #row.itemR(psys, "vertex_group_roughness_end")
587                 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
588
589                 #row = layout.row()
590                 #row.itemR(psys, "vertex_group_size")
591                 #row.itemR(psys, "vertex_group_size_negate", text="")
592                 
593                 #row = layout.row()
594                 #row.itemR(psys, "vertex_group_tangent")
595                 #row.itemR(psys, "vertex_group_tangent_negate", text="")
596                 
597                 #row = layout.row()
598                 #row.itemR(psys, "vertex_group_rotation")
599                 #row.itemR(psys, "vertex_group_rotation_negate", text="")
600                 
601                 #row = layout.row()
602                 #row.itemR(psys, "vertex_group_field")
603                 #row.itemR(psys, "vertex_group_field_negate", text="")
604                 
605 bpy.types.register(PARTICLE_PT_particles)
606 bpy.types.register(PARTICLE_PT_cache)
607 bpy.types.register(PARTICLE_PT_emission)
608 bpy.types.register(PARTICLE_PT_initial)
609 bpy.types.register(PARTICLE_PT_physics)
610 bpy.types.register(PARTICLE_PT_render)
611 bpy.types.register(PARTICLE_PT_draw)
612 bpy.types.register(PARTICLE_PT_children)
613 bpy.types.register(PARTICLE_PT_vertexgroups)