New point cache file format:
[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         if psys.settings==None:  return False
11         return psys.settings.type in ('EMITTER', 'REACTOR', 'HAIR')
12
13 class ParticleButtonsPanel(bpy.types.Panel):
14         __space_type__ = "BUTTONS_WINDOW"
15         __region_type__ = "WINDOW"
16         __context__ = "particle"
17
18         def poll(self, context):
19                 return particle_panel_poll(context)
20
21 class PARTICLE_PT_particles(ParticleButtonsPanel):
22         __show_header__ = False
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                 if ob:
33                         row = layout.row()
34
35                         row.template_list(ob, "particle_systems", ob, "active_particle_system_index")
36
37                         col = row.column(align=True)
38                         col.itemO("object.particle_system_add", icon="ICON_ZOOMIN", text="")
39                         col.itemO("object.particle_system_remove", icon="ICON_ZOOMOUT", text="")
40
41                 if psys:
42                         part = psys.settings
43                         
44                         split = layout.split(percentage=0.32)
45                         col = split.column()
46                         col.itemL(text="Name:")
47                         if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
48                                 col.itemL(text="Settings:")
49                                 col.itemL(text="Type:")
50                         
51                         col = split.column()
52                         col.itemR(psys, "name", text="")
53                         if part.type in ('EMITTER', 'REACTOR', 'HAIR'):
54                                 col.template_ID(psys, "settings", new="particle.new")
55                         
56                         #row = layout.row()
57                         #row.itemL(text="Viewport")
58                         #row.itemL(text="Render")
59                         
60                         if part:
61                                 if part.type not in ('EMITTER', 'REACTOR', 'HAIR'):
62                                         layout.itemL(text="No settings for fluid particles")
63                                         return
64                                 
65                                 row=col.row()
66                                 row.enabled = particle_panel_enabled(psys)
67                                 row.itemR(part, "type", text="")
68                                 row.itemR(psys, "seed")
69                                 
70                                 split = layout.split(percentage=0.65)
71                                 if part.type=='HAIR':
72                                         if psys.editable==True:
73                                                 split.itemO("particle.editable_set", text="Free Edit")
74                                         else:
75                                                 split.itemO("particle.editable_set", text="Make Editable")
76                                         row = split.row()
77                                         row.enabled = particle_panel_enabled(psys)
78                                         row.itemR(part, "hair_step")
79                                 elif part.type=='REACTOR':
80                                         split.enabled = particle_panel_enabled(psys)
81                                         split.itemR(psys, "reactor_target_object")
82                                         split.itemR(psys, "reactor_target_particle_system", text="Particle System")
83                 
84 class PARTICLE_PT_emission(ParticleButtonsPanel):
85         __label__ = "Emission"
86         
87         def poll(self, context):
88                 if particle_panel_poll(context):
89                         return not context.particle_system.point_cache.external
90                 else:
91                         return False
92         
93         def draw(self, context):
94                 layout = self.layout
95
96                 psys = context.particle_system
97                 part = psys.settings
98                 
99                 layout.enabled = particle_panel_enabled(psys)
100                 
101                 row = layout.row()
102                 row.itemR(part, "amount")
103                 
104                 split = layout.split()
105                 
106                 col = split.column(align=True)
107                 col.itemR(part, "start")
108                 col.itemR(part, "end")
109
110                 col = split.column(align=True)
111                 col.itemR(part, "lifetime")
112                 col.itemR(part, "random_lifetime", slider=True)
113                 
114                 layout.row().itemL(text="Emit From:")
115                 
116                 row = layout.row()
117                 row.itemR(part, "emit_from", expand=True)
118                 row = layout.row()
119                 row.itemR(part, "trand")
120                 if part.distribution!='GRID':
121                         row.itemR(part, "even_distribution")
122                 
123                 if part.emit_from=='FACE' or part.emit_from=='VOLUME':
124                         row = layout.row()
125                         row.itemR(part, "distribution", expand=True)
126                         
127                         row = layout.row()
128
129                         if part.distribution=='JIT':
130                                 row.itemR(part, "userjit", text="Particles/Face")
131                                 row.itemR(part, "jitter_factor", text="Jittering Amount", slider=True)
132                         elif part.distribution=='GRID':
133                                 row.itemR(part, "grid_resolution")
134
135 class PARTICLE_PT_cache(ParticleButtonsPanel):
136         __label__ = "Cache"
137         __default_closed__ = True
138         
139         def poll(self, context):
140                 psys = context.particle_system
141                 if psys==None:  return False
142                 if psys.settings==None:  return False
143                 phystype = psys.settings.physics_type
144                 if phystype == 'NO' or phystype == 'KEYED':
145                         return False
146                 return psys.settings.type in ('EMITTER', 'REACTOR')
147
148         def draw(self, context):
149                 layout = self.layout
150
151                 psys = context.particle_system
152                 part = psys.settings
153                 cache = psys.point_cache
154                 layout.set_context_pointer("PointCache", cache)
155                 
156                 row = layout.row()
157                 row.template_list(cache, "point_cache_list", cache, "active_point_cache_index")
158                 col = row.column(align=True)
159                 col.itemO("ptcache.add_new", icon="ICON_ZOOMIN", text="")
160                 col.itemO("ptcache.remove", icon="ICON_ZOOMOUT", text="")
161                 
162                 row = layout.row()
163                 row.itemL(text="File Name:")
164                 row.itemR(cache, "external")
165                 
166                 if cache.external:
167                         split = layout.split(percentage=0.80)
168                         split.itemR(cache, "name", text="")
169                         split.itemR(cache, "index", text="")
170                         
171                         layout.itemL(text="File Path:")
172                         layout.itemR(cache, "filepath", text="")
173                         
174                         layout.itemL(text=cache.info)
175                         
176                         #split = layout.split()
177                         
178                         #col = split.column(align=True)
179                         #col.itemR(part, "start")
180                         #col.itemR(part, "end")
181
182                         #col = split.column(align=True)
183                         #col.itemR(part, "lifetime")
184                         #col.itemR(part, "random_lifetime", slider=True)
185                 else:
186                         layout.itemR(cache, "name", text="")
187                         
188                         row = layout.row()
189                 
190                         if cache.baked == True:
191                                 row.itemO("ptcache.free_bake", text="Free Bake")
192                         else:
193                                 row.item_booleanO("ptcache.bake", "bake", True, text="Bake")
194                 
195                         subrow = row.row()
196                         subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
197                         subrow.itemO("ptcache.bake", "bake", False, text="Calculate to Current Frame")
198                         
199                         row = layout.row()
200                         row.enabled = particle_panel_enabled(psys)
201                         row.itemO("ptcache.bake_from_cache", text="Current Cache to Bake")
202                         row.itemR(cache, "step");
203                 
204                         row = layout.row()
205                         subrow = row.row()
206                         subrow.enabled = particle_panel_enabled(psys)
207                         subrow.itemR(cache, "quick_cache")
208                         row.itemR(cache, "disk_cache")
209                 
210                         layout.itemL(text=cache.info)
211                         
212                         layout.itemS()
213                         
214                         row = layout.row()
215                         row.item_booleanO("ptcache.bake_all", "bake", True, text="Bake All Dynamics")
216                         row.itemO("ptcache.free_bake_all", text="Free All Bakes")
217                         layout.itemO("ptcache.bake_all", "bake", False, text="Update All Dynamics to current frame")
218                 
219                 # for particles these are figured out automatically
220                 #row.itemR(cache, "start_frame")
221                 #row.itemR(cache, "end_frame")
222
223 class PARTICLE_PT_initial(ParticleButtonsPanel):
224         __label__ = "Velocity"
225         
226         def poll(self, context):
227                 if particle_panel_poll(context):
228                         psys = context.particle_system
229                         return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.external
230                 else:
231                         return False
232
233         def draw(self, context):
234                 layout = self.layout
235
236                 psys = context.particle_system
237                 part = psys.settings
238                 
239                 layout.enabled = particle_panel_enabled(psys)
240                                 
241                 layout.row().itemL(text="Direction:")
242         
243                 split = layout.split()
244                         
245                 sub = split.column()
246                 sub.itemR(part, "normal_factor")
247                 if part.emit_from=='PARTICLE':
248                         sub.itemR(part, "particle_factor")
249                 else:
250                         sub.itemR(part, "object_factor", slider=True)
251                 sub.itemR(part, "random_factor")
252                 sub.itemR(part, "tangent_factor")
253                 sub.itemR(part, "tangent_phase", slider=True)
254                 
255                 sub = split.column()
256                 sub.itemL(text="TODO:")
257                 sub.itemL(text="Object aligned")
258                 sub.itemL(text="direction: X, Y, Z")
259                 
260                 if part.type=='REACTOR':
261                         sub.itemR(part, "reactor_factor")
262                         sub.itemR(part, "reaction_shape", slider=True)
263                 else:
264                         sub.itemL(text="")
265                 
266                 layout.row().itemL(text="Rotation:")
267                 split = layout.split()
268                         
269                 sub = split.column()
270                 
271                 sub.itemR(part, "rotation_mode", text="Axis")
272                 split = layout.split()
273                         
274                 sub = split.column()
275                 sub.itemR(part, "rotation_dynamic")
276                 sub.itemR(part, "random_rotation_factor", slider=True)
277                 sub = split.column()
278                 sub.itemR(part, "phase_factor", slider=True)
279                 sub.itemR(part, "random_phase_factor", text="Random", slider=True)
280
281                 layout.row().itemL(text="Angular velocity:")
282                 layout.row().itemR(part, "angular_velocity_mode", expand=True)
283                 split = layout.split()
284                         
285                 sub = split.column()
286                 
287                 sub.itemR(part, "angular_velocity_factor", text="")
288                 
289 class PARTICLE_PT_physics(ParticleButtonsPanel):
290         __label__ = "Physics"
291         
292         def poll(self, context):
293                 if particle_panel_poll(context):
294                         return not context.particle_system.point_cache.external
295                 else:
296                         return False
297
298         def draw(self, context):
299                 layout = self.layout
300
301                 psys = context.particle_system
302                 part = psys.settings
303                 
304                 layout.enabled = particle_panel_enabled(psys)
305
306                 row = layout.row()
307                 row.itemR(part, "physics_type", expand=True)
308                 if part.physics_type != 'NO':
309                         row = layout.row()
310                         col = row.column(align=True)
311                         col.itemR(part, "particle_size")
312                         col.itemR(part, "random_size", slider=True)
313                         col = row.column(align=True)
314                         col.itemR(part, "mass")
315                         col.itemR(part, "sizemass", text="Multiply mass with size")
316                         
317                 if part.physics_type == 'NEWTON':
318                         split = layout.split()
319                         sub = split.column()
320                         
321                         sub.itemL(text="Forces:")
322                         sub.itemR(part, "brownian_factor")
323                         sub.itemR(part, "drag_factor", slider=True)
324                         sub.itemR(part, "damp_factor", slider=True)
325                         sub.itemR(part, "integrator")
326                         sub = split.column()
327                         sub.itemR(part, "acceleration")
328                         
329                 elif part.physics_type == 'KEYED':
330                         split = layout.split()
331                         sub = split.column()
332                         
333                         row = layout.row()
334                         col = row.column()
335                         col.active = not psys.keyed_timing
336                         col.itemR(part, "keyed_loops", text="Loops")
337                         row.itemR(psys, "keyed_timing", text="Use Timing")
338                         
339                         layout.itemL(text="Keys:")
340                 elif part.physics_type=='BOIDS':
341                         boids = part.boids
342                         
343
344                         row = layout.row()
345                         row.itemR(boids, "allow_flight")
346                         row.itemR(boids, "allow_land")
347                         row.itemR(boids, "allow_climb")
348                         
349                         split = layout.split()
350                         
351                         sub = split.column()
352                         col = sub.column(align=True)
353                         col.active = boids.allow_flight
354                         col.itemR(boids, "air_max_speed")
355                         col.itemR(boids, "air_min_speed", slider="True")
356                         col.itemR(boids, "air_max_acc", slider="True")
357                         col.itemR(boids, "air_max_ave", slider="True")
358                         col.itemR(boids, "air_personal_space")
359                         row = col.row()
360                         row.active = (boids.allow_land or boids.allow_climb) and boids.allow_flight
361                         row.itemR(boids, "landing_smoothness")
362                         
363                         sub = split.column()
364                         col = sub.column(align=True)
365                         col.active = boids.allow_land or boids.allow_climb
366                         col.itemR(boids, "land_max_speed")
367                         col.itemR(boids, "land_jump_speed")
368                         col.itemR(boids, "land_max_acc", slider="True")
369                         col.itemR(boids, "land_max_ave", slider="True")
370                         col.itemR(boids, "land_personal_space")
371                         col.itemR(boids, "land_stick_force")
372                         
373                         row = layout.row()
374                         
375                         col = row.column(align=True)
376                         col.itemL(text="Battle:")
377                         col.itemR(boids, "health")
378                         col.itemR(boids, "strength")
379                         col.itemR(boids, "aggression")
380                         col.itemR(boids, "accuracy")
381                         col.itemR(boids, "range")
382                         
383                         col = row.column()
384                         col.itemL(text="Misc:")
385                         col.itemR(part, "gravity")
386                         col.itemR(boids, "banking", slider=True)
387                         col.itemR(boids, "height", slider=True)
388                         
389                 if part.physics_type=='NEWTON':
390                         sub.itemR(part, "size_deflect")
391                         sub.itemR(part, "die_on_collision")
392                         sub.itemR(part, "sticky")
393                 elif part.physics_type=='KEYED' or part.physics_type=='BOIDS':
394                         if part.physics_type=='BOIDS':
395                                 layout.itemL(text="Relations:")
396                         
397                         row = layout.row()
398                         row.template_list(psys, "targets", psys, "active_particle_target_index")
399                         
400                         col = row.column()
401                         subrow = col.row()
402                         subcol = subrow.column(align=True)
403                         subcol.itemO("particle.new_target", icon="ICON_ZOOMIN", text="")
404                         subcol.itemO("particle.remove_target", icon="ICON_ZOOMOUT", text="")
405                         subrow = col.row()
406                         subcol = subrow.column(align=True)
407                         subcol.itemO("particle.target_move_up", icon="VICON_MOVE_UP", text="")
408                         subcol.itemO("particle.target_move_down", icon="VICON_MOVE_DOWN", text="")
409                         
410                         key = psys.active_particle_target
411                         if key:
412                                 row = layout.row()
413                                 if part.physics_type=='KEYED':
414                                         col = row.column()
415                                         #doesn't work yet
416                                         #col.red_alert = key.valid
417                                         col.itemR(key, "object", text="")
418                                         col.itemR(key, "system", text="System")
419                                         col = row.column();
420                                         col.active = psys.keyed_timing
421                                         col.itemR(key, "time")
422                                         col.itemR(key, "duration")
423                                 else:
424                                         subrow = row.row()
425                                         #doesn't work yet
426                                         #subrow.red_alert = key.valid
427                                         subrow.itemR(key, "object", text="")
428                                         subrow.itemR(key, "system", text="System")
429                                         
430                                         layout.itemR(key, "mode", expand=True)
431
432 class PARTICLE_PT_boidbrain(ParticleButtonsPanel):
433         __label__ = "Boid Brain"
434
435         def poll(self, context):
436                 psys = context.particle_system
437                 if psys==None:  return False
438                 if psys.settings==None:  return False
439                 if psys.point_cache.external: return False
440                 return psys.settings.physics_type=='BOIDS'
441         
442         def draw(self, context):
443                 boids = context.particle_system.settings.boids
444                 layout = self.layout
445                 
446                 layout.enabled = particle_panel_enabled(psys)
447                 
448                 # Currently boids can only use the first state so these are commented out for now.
449                 #row = layout.row()
450                 #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
451                 #col = row.row()
452                 #subrow = col.row(align=True)
453                 #subrow.itemO("boid.boidstate_add", icon="ICON_ZOOMIN", text="")
454                 #subrow.itemO("boid.boidstate_del", icon="ICON_ZOOMOUT", text="")
455                 #subrow = row.row(align=True)
456                 #subrow.itemO("boid.boidstate_move_up", icon="VICON_MOVE_UP", text="")
457                 #subrow.itemO("boid.boidstate_move_down", icon="VICON_MOVE_DOWN", text="")
458                 
459                 state = boids.active_boid_state
460                 
461                 #layout.itemR(state, "name", text="State name")
462                 
463                 row = layout.row()
464                 row.itemR(state, "ruleset_type")
465                 if state.ruleset_type=='FUZZY':
466                         row.itemR(state, "rule_fuzziness", slider=True)
467                 else:
468                         row.itemL(text="")
469                 
470                 row = layout.row()
471                 row.template_list(state, "rules", state, "active_boid_rule_index")
472                 
473                 col = row.column()
474                 subrow = col.row()
475                 subcol = subrow.column(align=True)
476                 subcol.item_menu_enumO("boid.boidrule_add", "type", icon="ICON_ZOOMIN", text="")
477                 subcol.itemO("boid.boidrule_del", icon="ICON_ZOOMOUT", text="")
478                 subrow = col.row()
479                 subcol = subrow.column(align=True)
480                 subcol.itemO("boid.boidrule_move_up", icon="VICON_MOVE_UP", text="")
481                 subcol.itemO("boid.boidrule_move_down", icon="VICON_MOVE_DOWN", text="")
482                 
483                 rule = state.active_boid_rule
484                 
485                 if rule:
486                         row = layout.row()
487                         row.itemR(rule, "name", text="")
488                         #somebody make nice icons for boids here please! -jahka
489                         row.itemR(rule, "in_air", icon="VICON_MOVE_UP", text="")
490                         row.itemR(rule, "on_land", icon="VICON_MOVE_DOWN", text="")
491                         
492                         row = layout.row()
493
494                         if rule.type == 'GOAL':
495                                 row.itemR(rule, "object")
496                                 row = layout.row()
497                                 row.itemR(rule, "predict")
498                         elif rule.type == 'AVOID':
499                                 row.itemR(rule, "object")
500                                 row = layout.row()
501                                 row.itemR(rule, "predict")
502                                 row.itemR(rule, "fear_factor")
503                         elif rule.type == 'FOLLOW_PATH':
504                                 row.itemL(text="Not yet functional.")
505                         elif rule.type == 'AVOID_COLLISION':
506                                 row.itemR(rule, "boids")
507                                 row.itemR(rule, "deflectors")
508                                 row.itemR(rule, "look_ahead")
509                         elif rule.type == 'FOLLOW_LEADER':
510                                 row.itemR(rule, "object", text="")
511                                 row.itemR(rule, "distance")
512                                 row = layout.row()
513                                 row.itemR(rule, "line")
514                                 subrow = row.row()
515                                 subrow.active = rule.line
516                                 subrow.itemR(rule, "queue_size")
517                         elif rule.type == 'AVERAGE_SPEED':
518                                 row.itemR(rule, "speed", slider=True)
519                                 row.itemR(rule, "wander", slider=True)
520                                 row.itemR(rule, "level", slider=True)
521                         elif rule.type == 'FIGHT':
522                                 row.itemR(rule, "distance")
523                                 row.itemR(rule, "flee_distance")
524                 
525
526 class PARTICLE_PT_render(ParticleButtonsPanel):
527         __label__ = "Render"
528         
529         def poll(self, context):
530                 psys = context.particle_system
531                 if psys==None: return False
532                 if psys.settings==None: return False
533                 return True;
534                 
535         def draw(self, context):
536                 layout = self.layout
537
538                 psys = context.particle_system
539                 part = psys.settings
540
541                 row = layout.row()
542                 row.itemR(part, "material")
543                 row.itemR(psys, "parent");
544                 
545                 split = layout.split()
546                         
547                 sub = split.column()
548                 sub.itemR(part, "emitter");
549                 sub.itemR(part, "parent");
550                 sub = split.column()
551                 sub.itemR(part, "unborn");
552                 sub.itemR(part, "died");
553                 
554                 row = layout.row()
555                 row.itemR(part, "ren_as", expand=True)
556                 
557                 split = layout.split()
558                         
559                 sub = split.column()
560                 
561                 if part.ren_as == 'LINE':
562                         sub.itemR(part, "line_length_tail")
563                         sub.itemR(part, "line_length_head")
564                         sub = split.column()
565                         sub.itemR(part, "velocity_length")
566                 elif part.ren_as == 'PATH':
567                 
568                         if (part.type!='HAIR' and part.physics_type!='KEYED' and psys.point_cache.baked==False):
569                                 box = layout.box()
570                                 box.itemL(text="Baked or keyed particles needed for correct rendering.")
571                                 return
572                                 
573                         sub.itemR(part, "render_strand")
574                         colsub = sub.column()
575                         colsub.active = part.render_strand == False
576                         colsub.itemR(part, "render_adaptive")
577                         colsub = sub.column()
578                         colsub.active = part.render_adaptive or part.render_strand == True
579                         colsub.itemR(part, "adaptive_angle")
580                         colsub = sub.column()
581                         colsub.active = part.render_adaptive == True and part.render_strand == False
582                         colsub.itemR(part, "adaptive_pix")
583                         sub.itemR(part, "hair_bspline")
584                         sub.itemR(part, "render_step", text="Steps")
585                         sub = split.column()    
586
587                         sub.itemL(text="Timing:")
588                         sub.itemR(part, "abs_path_time")
589                         sub.itemR(part, "path_start", text="Start", slider= not part.abs_path_time)
590                         sub.itemR(part, "path_end", text="End", slider= not part.abs_path_time)         
591                         sub.itemR(part, "random_length", text="Random", slider=True)
592                         
593                         row = layout.row()
594                         col = row.column()
595                         
596                         if part.type=='HAIR' and part.render_strand==True and part.child_type=='FACES':
597                                 layout.itemR(part, "enable_simplify")
598                                 if part.enable_simplify==True:
599                                         row = layout.row()
600                                         row.itemR(part, "simplify_refsize")
601                                         row.itemR(part, "simplify_rate")
602                                         row.itemR(part, "simplify_transition")
603                                         row = layout.row()
604                                         row.itemR(part, "viewport")
605                                         subrow = row.row()
606                                         subrow.active = part.viewport==True
607                                         subrow.itemR(part, "simplify_viewport")
608                         
609
610                 elif part.ren_as == 'OBJECT':
611                         sub.itemR(part, "dupli_object")
612                 elif part.ren_as == 'GROUP':
613                         sub.itemR(part, "dupli_group")
614                         split = layout.split()
615                         sub = split.column()
616                         sub.itemR(part, "whole_group")
617                         sub = split.column()
618                         colsub = sub.column()
619                         colsub.active = part.whole_group == False
620                         colsub.itemR(part, "rand_group")
621                         
622                 elif part.ren_as == 'BILLBOARD':
623                         sub.itemL(text="Align:")
624                         
625                         row = layout.row()
626                         row.itemR(part, "billboard_align", expand=True)
627                         row.itemR(part, "billboard_lock", text="Lock")
628                         row = layout.row()
629                         row.itemR(part, "billboard_object")
630                 
631                         row = layout.row()
632                         col = row.column(align=True)
633                         col.itemL(text="Tilt:")
634                         col.itemR(part, "billboard_tilt", text="Angle", slider=True)
635                         col.itemR(part, "billboard_random_tilt", slider=True)
636                         col = row.column()
637                         col.itemR(part, "billboard_offset")
638                         
639                         row = layout.row()
640                         row.itemR(psys, "billboard_normal_uv")
641                         row = layout.row()
642                         row.itemR(psys, "billboard_time_index_uv")
643                         
644                         row = layout.row()
645                         row.itemL(text="Split uv's:")
646                         row.itemR(part, "billboard_uv_split", text="Number of splits")
647                         row = layout.row()
648                         row.itemR(psys, "billboard_split_uv")
649                         row = layout.row()
650                         row.itemL(text="Animate:")
651                         row.itemR(part, "billboard_animation", expand=True)
652                         row.itemL(text="Offset:")
653                         row.itemR(part, "billboard_split_offset", expand=True)
654                 if part.ren_as == 'HALO' or part.ren_as == 'LINE' or part.ren_as=='BILLBOARD':
655                         row = layout.row()
656                         col = row.column()
657                         col.itemR(part, "trail_count")
658                         if part.trail_count > 1:
659                                 col.itemR(part, "abs_path_time", text="Length in frames")
660                                 col = row.column()
661                                 col.itemR(part, "path_end", text="Length", slider=not part.abs_path_time)
662                                 col.itemR(part, "random_length", text="Random", slider=True)
663                         else:
664                                 col = row.column()
665                                 col.itemL(text="")
666                                 
667 class PARTICLE_PT_draw(ParticleButtonsPanel):
668         __label__ = "Display"
669         __default_closed__ = True
670         
671         def poll(self, context):
672                 psys = context.particle_system
673                 if psys==None: return False
674                 if psys.settings==None: return False
675                 return True;
676         
677         def draw(self, context):
678                 layout = self.layout
679
680                 psys = context.particle_system
681                 part = psys.settings
682                 
683                 row = layout.row()
684                 row.itemR(part, "draw_as", expand=True)
685                 
686                 if part.draw_as=='NONE' or (part.ren_as=='NONE' and part.draw_as=='RENDER'):
687                         return
688                         
689                 path = (part.ren_as=='PATH' and part.draw_as=='RENDER') or part.draw_as=='PATH'
690                         
691                 if path and part.type!='HAIR' and part.physics_type!='KEYED' and psys.point_cache.baked==False:
692                         box = layout.box()
693                         box.itemL(text="Baked or keyed particles needed for correct drawing.")
694                         return
695                 
696                 row = layout.row()
697                 row.itemR(part, "display", slider=True)
698                 if part.draw_as!='RENDER' or part.ren_as=='HALO':
699                         row.itemR(part, "draw_size")
700                 else:
701                         row.itemL(text="")
702                 
703                 row = layout.row()
704                 col = row.column()
705                 col.itemR(part, "show_size")
706                 col.itemR(part, "velocity")
707                 col.itemR(part, "num")
708                 if part.physics_type == 'BOIDS':
709                         col.itemR(part, "draw_health")
710                 
711                 col = row.column()
712                 col.itemR(part, "material_color", text="Use material color")
713                 
714                 if (path):
715                         box = col.box()                         
716                         box.itemR(part, "draw_step")
717                 else:
718                         subcol = col.column()
719                         subcol.active = part.material_color==False
720                         #subcol.itemL(text="color")
721                         #subcol.itemL(text="Override material color")
722
723 class PARTICLE_PT_children(ParticleButtonsPanel):
724         __label__ = "Children"
725         __default_closed__ = True
726
727         def draw(self, context):
728                 layout = self.layout
729
730                 psys = context.particle_system
731                 part = psys.settings
732                 
733                 layout.row().itemR(part, "child_type", expand=True)
734                 
735                 if part.child_type=='NONE':
736                         return
737                 
738                 row = layout.row()
739                 
740                 col = row.column(align=True)
741                 col.itemR(part, "child_nbr", text="Display")
742                 col.itemR(part, "rendered_child_nbr", text="Render")
743                 
744                 col = row.column(align=True)
745                 
746                 if part.child_type=='FACES':
747                         col.itemR(part, "virtual_parents", slider=True)
748                 else:
749                         col.itemR(part, "child_radius", text="Radius")
750                         col.itemR(part, "child_roundness", text="Roundness", slider=True)
751                 
752                         col = row.column(align=True)
753                         col.itemR(part, "child_size", text="Size")
754                         col.itemR(part, "child_random_size", text="Random")
755                 
756                 layout.row().itemL(text="Effects:")
757                 
758                 row = layout.row()
759                 
760                 col = row.column(align=True)
761                 col.itemR(part, "clump_factor", slider=True)
762                 col.itemR(part, "clumppow", slider=True)
763                 
764                 col = row.column(align=True)
765                 col.itemR(part, "rough_endpoint")
766                 col.itemR(part, "rough_end_shape")
767
768                 row = layout.row()
769                 
770                 col = row.column(align=True)
771                 col.itemR(part, "rough1")
772                 col.itemR(part, "rough1_size")
773
774                 col = row.column(align=True)
775                 col.itemR(part, "rough2")
776                 col.itemR(part, "rough2_size")
777                 col.itemR(part, "rough2_thres", slider=True)
778                 
779                 row = layout.row()
780                 col = row.column(align=True)
781                 col.itemR(part, "child_length", slider=True)
782                 col.itemR(part, "child_length_thres", slider=True)
783                 
784                 col = row.column(align=True)
785                 col.itemL(text="Space reserved for")
786                 col.itemL(text="hair parting controls")
787                 
788                 layout.row().itemL(text="Kink:")
789                 layout.row().itemR(part, "kink", expand=True)
790                 
791                 split = layout.split()
792                 
793                 sub = split.column()
794                 sub.itemR(part, "kink_amplitude")
795                 sub.itemR(part, "kink_frequency")
796                 sub = split.column()
797                 sub.itemR(part, "kink_shape", slider=True)
798
799 class PARTICLE_PT_effectors(ParticleButtonsPanel):
800         __label__ = "Effectors"
801         __default_closed__ = True
802         
803         def draw(self, context):
804                 layout = self.layout
805
806                 psys = context.particle_system
807                 part = psys.settings
808                 
809                 layout.itemR(part, "effector_group")
810                 
811                 layout.itemR(part, "eweight_all", slider=True)
812                 
813                 layout.itemS()
814                 layout.itemR(part, "eweight_spherical", slider=True)
815                 layout.itemR(part, "eweight_vortex", slider=True)
816                 layout.itemR(part, "eweight_magnetic", slider=True)
817                 layout.itemR(part, "eweight_wind", slider=True)
818                 layout.itemR(part, "eweight_curveguide", slider=True)
819                 layout.itemR(part, "eweight_texture", slider=True)
820                 layout.itemR(part, "eweight_harmonic", slider=True)
821                 layout.itemR(part, "eweight_charge", slider=True)
822                 layout.itemR(part, "eweight_lennardjones", slider=True)
823                 
824 class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
825         __label__ = "Vertexgroups"
826         __default_closed__ = True
827
828         def draw(self, context):
829                 layout = self.layout
830
831                 psys = context.particle_system
832                 part = psys.settings
833                 
834                 layout.itemL(text="Nothing here yet.")
835
836                 #row = layout.row()
837                 #row.itemL(text="Vertex Group")
838                 #row.itemL(text="Negate")
839
840                 
841                 #row = layout.row()
842                 #row.itemR(psys, "vertex_group_density")
843                 #row.itemR(psys, "vertex_group_density_negate", text="")
844                 
845                 #row = layout.row()
846                 #row.itemR(psys, "vertex_group_velocity")
847                 #row.itemR(psys, "vertex_group_velocity_negate", text="")
848                 
849                 #row = layout.row()
850                 #row.itemR(psys, "vertex_group_length")
851                 #row.itemR(psys, "vertex_group_length_negate", text="")
852                 
853                 #row = layout.row()
854                 #row.itemR(psys, "vertex_group_clump")
855                 #row.itemR(psys, "vertex_group_clump_negate", text="")
856                 
857                 #row = layout.row()
858                 #row.itemR(psys, "vertex_group_kink")
859                 #row.itemR(psys, "vertex_group_kink_negate", text="")
860                 
861                 #row = layout.row()
862                 #row.itemR(psys, "vertex_group_roughness1")
863                 #row.itemR(psys, "vertex_group_roughness1_negate", text="")
864                 
865                 #row = layout.row()
866                 #row.itemR(psys, "vertex_group_roughness2")
867                 #row.itemR(psys, "vertex_group_roughness2_negate", text="")
868                 
869                 #row = layout.row()
870                 #row.itemR(psys, "vertex_group_roughness_end")
871                 #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
872
873                 #row = layout.row()
874                 #row.itemR(psys, "vertex_group_size")
875                 #row.itemR(psys, "vertex_group_size_negate", text="")
876                 
877                 #row = layout.row()
878                 #row.itemR(psys, "vertex_group_tangent")
879                 #row.itemR(psys, "vertex_group_tangent_negate", text="")
880                 
881                 #row = layout.row()
882                 #row.itemR(psys, "vertex_group_rotation")
883                 #row.itemR(psys, "vertex_group_rotation_negate", text="")
884                 
885                 #row = layout.row()
886                 #row.itemR(psys, "vertex_group_field")
887                 #row.itemR(psys, "vertex_group_field_negate", text="")
888                 
889 bpy.types.register(PARTICLE_PT_particles)
890 bpy.types.register(PARTICLE_PT_cache)
891 bpy.types.register(PARTICLE_PT_emission)
892 bpy.types.register(PARTICLE_PT_initial)
893 bpy.types.register(PARTICLE_PT_physics)
894 bpy.types.register(PARTICLE_PT_boidbrain)
895 bpy.types.register(PARTICLE_PT_render)
896 bpy.types.register(PARTICLE_PT_draw)
897 bpy.types.register(PARTICLE_PT_children)
898 bpy.types.register(PARTICLE_PT_effectors)
899 bpy.types.register(PARTICLE_PT_vertexgroups)