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