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