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