Merging r42800 through r42895 from trunk into soc-2011-tomato
[blender.git] / release / scripts / startup / bl_ui / properties_object_constraint.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from bpy.types import Panel
22
23
24 class ConstraintButtonsPanel():
25     bl_space_type = 'PROPERTIES'
26     bl_region_type = 'WINDOW'
27     bl_context = "constraint"
28
29     def draw_constraint(self, context, con):
30         layout = self.layout
31
32         box = layout.template_constraint(con)
33
34         if box:
35             # match enum type to our functions, avoids a lookup table.
36             getattr(self, con.type)(context, box, con)
37
38             if con.type not in {'RIGID_BODY_JOINT', 'NULL'}:
39                 box.prop(con, "influence")
40
41     def space_template(self, layout, con, target=True, owner=True):
42         if target or owner:
43
44             split = layout.split(percentage=0.2)
45
46             split.label(text="Space:")
47             row = split.row()
48
49             if target:
50                 row.prop(con, "target_space", text="")
51
52             if target and owner:
53                 row.label(icon='ARROW_LEFTRIGHT')
54
55             if owner:
56                 row.prop(con, "owner_space", text="")
57
58     def target_template(self, layout, con, subtargets=True):
59         layout.prop(con, "target")  # XXX limiting settings for only 'curves' or some type of object
60
61         if con.target and subtargets:
62             if con.target.type == 'ARMATURE':
63                 layout.prop_search(con, "subtarget", con.target.data, "bones", text="Bone")
64
65                 if hasattr(con, "head_tail"):
66                     row = layout.row()
67                     row.label(text="Head/Tail:")
68                     row.prop(con, "head_tail", text="")
69             elif con.target.type in {'MESH', 'LATTICE'}:
70                 layout.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
71
72     def ik_template(self, layout, con):
73         # only used for iTaSC
74         layout.prop(con, "pole_target")
75
76         if con.pole_target and con.pole_target.type == 'ARMATURE':
77             layout.prop_search(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
78
79         if con.pole_target:
80             row = layout.row()
81             row.label()
82             row.prop(con, "pole_angle")
83
84         split = layout.split(percentage=0.33)
85         col = split.column()
86         col.prop(con, "use_tail")
87         col.prop(con, "use_stretch")
88
89         col = split.column()
90         col.prop(con, "chain_count")
91         col.prop(con, "use_target")
92
93     def CHILD_OF(self, context, layout, con):
94         self.target_template(layout, con)
95
96         split = layout.split()
97
98         col = split.column()
99         col.label(text="Location:")
100         col.prop(con, "use_location_x", text="X")
101         col.prop(con, "use_location_y", text="Y")
102         col.prop(con, "use_location_z", text="Z")
103
104         col = split.column()
105         col.label(text="Rotation:")
106         col.prop(con, "use_rotation_x", text="X")
107         col.prop(con, "use_rotation_y", text="Y")
108         col.prop(con, "use_rotation_z", text="Z")
109
110         col = split.column()
111         col.label(text="Scale:")
112         col.prop(con, "use_scale_x", text="X")
113         col.prop(con, "use_scale_y", text="Y")
114         col.prop(con, "use_scale_z", text="Z")
115
116         row = layout.row()
117         row.operator("constraint.childof_set_inverse")
118         row.operator("constraint.childof_clear_inverse")
119
120     def TRACK_TO(self, context, layout, con):
121         self.target_template(layout, con)
122
123         row = layout.row()
124         row.label(text="To:")
125         row.prop(con, "track_axis", expand=True)
126
127         row = layout.row()
128         row.prop(con, "up_axis", text="Up")
129         row.prop(con, "use_target_z")
130
131         self.space_template(layout, con)
132
133     def IK(self, context, layout, con):
134         if context.object.pose.ik_solver == 'ITASC':
135             layout.prop(con, "ik_type")
136             getattr(self, 'IK_' + con.ik_type)(context, layout, con)
137         else:
138             # Legacy IK constraint
139             self.target_template(layout, con)
140             layout.prop(con, "pole_target")
141
142             if con.pole_target and con.pole_target.type == 'ARMATURE':
143                 layout.prop_search(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
144
145             if con.pole_target:
146                 row = layout.row()
147                 row.prop(con, "pole_angle")
148                 row.label()
149
150             split = layout.split()
151             col = split.column()
152             col.prop(con, "iterations")
153             col.prop(con, "chain_count")
154
155             col.label(text="Weight:")
156             col.prop(con, "weight", text="Position", slider=True)
157             sub = col.column()
158             sub.active = con.use_rotation
159             sub.prop(con, "orient_weight", text="Rotation", slider=True)
160
161             col = split.column()
162             col.prop(con, "use_tail")
163             col.prop(con, "use_stretch")
164             col.separator()
165             col.prop(con, "use_target")
166             col.prop(con, "use_rotation")
167
168     def IK_COPY_POSE(self, context, layout, con):
169         self.target_template(layout, con)
170         self.ik_template(layout, con)
171
172         row = layout.row()
173         row.label(text="Axis Ref:")
174         row.prop(con, "reference_axis", expand=True)
175         split = layout.split(percentage=0.33)
176         split.row().prop(con, "use_location")
177         row = split.row()
178         row.prop(con, "weight", text="Weight", slider=True)
179         row.active = con.use_location
180         split = layout.split(percentage=0.33)
181         row = split.row()
182         row.label(text="Lock:")
183         row = split.row()
184         row.prop(con, "lock_location_x", text="X")
185         row.prop(con, "lock_location_y", text="Y")
186         row.prop(con, "lock_location_z", text="Z")
187         split.active = con.use_location
188
189         split = layout.split(percentage=0.33)
190         split.row().prop(con, "use_rotation")
191         row = split.row()
192         row.prop(con, "orient_weight", text="Weight", slider=True)
193         row.active = con.use_rotation
194         split = layout.split(percentage=0.33)
195         row = split.row()
196         row.label(text="Lock:")
197         row = split.row()
198         row.prop(con, "lock_rotation_x", text="X")
199         row.prop(con, "lock_rotation_y", text="Y")
200         row.prop(con, "lock_rotation_z", text="Z")
201         split.active = con.use_rotation
202
203     def IK_DISTANCE(self, context, layout, con):
204         self.target_template(layout, con)
205         self.ik_template(layout, con)
206
207         layout.prop(con, "limit_mode")
208
209         row = layout.row()
210         row.prop(con, "weight", text="Weight", slider=True)
211         row.prop(con, "distance", text="Distance", slider=True)
212
213     def FOLLOW_PATH(self, context, layout, con):
214         self.target_template(layout, con)
215
216         split = layout.split()
217
218         col = split.column()
219         col.prop(con, "use_curve_follow")
220         col.prop(con, "use_curve_radius")
221
222         col = split.column()
223         col.prop(con, "use_fixed_location")
224         if con.use_fixed_location:
225             col.prop(con, "offset_factor", text="Offset")
226         else:
227             col.prop(con, "offset")
228
229         row = layout.row()
230         row.label(text="Forward:")
231         row.prop(con, "forward_axis", expand=True)
232
233         row = layout.row()
234         row.prop(con, "up_axis", text="Up")
235         row.label()
236
237     def LIMIT_ROTATION(self, context, layout, con):
238         split = layout.split()
239
240         col = split.column(align=True)
241         col.prop(con, "use_limit_x")
242         sub = col.column()
243         sub.active = con.use_limit_x
244         sub.prop(con, "min_x", text="Min")
245         sub.prop(con, "max_x", text="Max")
246
247         col = split.column(align=True)
248         col.prop(con, "use_limit_y")
249         sub = col.column()
250         sub.active = con.use_limit_y
251         sub.prop(con, "min_y", text="Min")
252         sub.prop(con, "max_y", text="Max")
253
254         col = split.column(align=True)
255         col.prop(con, "use_limit_z")
256         sub = col.column()
257         sub.active = con.use_limit_z
258         sub.prop(con, "min_z", text="Min")
259         sub.prop(con, "max_z", text="Max")
260
261         layout.prop(con, "use_transform_limit")
262
263         row = layout.row()
264         row.label(text="Convert:")
265         row.prop(con, "owner_space", text="")
266
267     def LIMIT_LOCATION(self, context, layout, con):
268         split = layout.split()
269
270         col = split.column()
271         col.prop(con, "use_min_x")
272         sub = col.column()
273         sub.active = con.use_min_x
274         sub.prop(con, "min_x", text="")
275         col.prop(con, "use_max_x")
276         sub = col.column()
277         sub.active = con.use_max_x
278         sub.prop(con, "max_x", text="")
279
280         col = split.column()
281         col.prop(con, "use_min_y")
282         sub = col.column()
283         sub.active = con.use_min_y
284         sub.prop(con, "min_y", text="")
285         col.prop(con, "use_max_y")
286         sub = col.column()
287         sub.active = con.use_max_y
288         sub.prop(con, "max_y", text="")
289
290         col = split.column()
291         col.prop(con, "use_min_z")
292         sub = col.column()
293         sub.active = con.use_min_z
294         sub.prop(con, "min_z", text="")
295         col.prop(con, "use_max_z")
296         sub = col.column()
297         sub.active = con.use_max_z
298         sub.prop(con, "max_z", text="")
299
300         row = layout.row()
301         row.prop(con, "use_transform_limit")
302         row.label()
303
304         row = layout.row()
305         row.label(text="Convert:")
306         row.prop(con, "owner_space", text="")
307
308     def LIMIT_SCALE(self, context, layout, con):
309         split = layout.split()
310
311         col = split.column()
312         col.prop(con, "use_min_x")
313         sub = col.column()
314         sub.active = con.use_min_x
315         sub.prop(con, "min_x", text="")
316         col.prop(con, "use_max_x")
317         sub = col.column()
318         sub.active = con.use_max_x
319         sub.prop(con, "max_x", text="")
320
321         col = split.column()
322         col.prop(con, "use_min_y")
323         sub = col.column()
324         sub.active = con.use_min_y
325         sub.prop(con, "min_y", text="")
326         col.prop(con, "use_max_y")
327         sub = col.column()
328         sub.active = con.use_max_y
329         sub.prop(con, "max_y", text="")
330
331         col = split.column()
332         col.prop(con, "use_min_z")
333         sub = col.column()
334         sub.active = con.use_min_z
335         sub.prop(con, "min_z", text="")
336         col.prop(con, "use_max_z")
337         sub = col.column()
338         sub.active = con.use_max_z
339         sub.prop(con, "max_z", text="")
340
341         row = layout.row()
342         row.prop(con, "use_transform_limit")
343         row.label()
344
345         row = layout.row()
346         row.label(text="Convert:")
347         row.prop(con, "owner_space", text="")
348
349     def COPY_ROTATION(self, context, layout, con):
350         self.target_template(layout, con)
351
352         split = layout.split()
353
354         col = split.column()
355         col.prop(con, "use_x", text="X")
356         sub = col.column()
357         sub.active = con.use_x
358         sub.prop(con, "invert_x", text="Invert")
359
360         col = split.column()
361         col.prop(con, "use_y", text="Y")
362         sub = col.column()
363         sub.active = con.use_y
364         sub.prop(con, "invert_y", text="Invert")
365
366         col = split.column()
367         col.prop(con, "use_z", text="Z")
368         sub = col.column()
369         sub.active = con.use_z
370         sub.prop(con, "invert_z", text="Invert")
371
372         layout.prop(con, "use_offset")
373
374         self.space_template(layout, con)
375
376     def COPY_LOCATION(self, context, layout, con):
377         self.target_template(layout, con)
378
379         split = layout.split()
380
381         col = split.column()
382         col.prop(con, "use_x", text="X")
383         sub = col.column()
384         sub.active = con.use_x
385         sub.prop(con, "invert_x", text="Invert")
386
387         col = split.column()
388         col.prop(con, "use_y", text="Y")
389         sub = col.column()
390         sub.active = con.use_y
391         sub.prop(con, "invert_y", text="Invert")
392
393         col = split.column()
394         col.prop(con, "use_z", text="Z")
395         sub = col.column()
396         sub.active = con.use_z
397         sub.prop(con, "invert_z", text="Invert")
398
399         layout.prop(con, "use_offset")
400
401         self.space_template(layout, con)
402
403     def COPY_SCALE(self, context, layout, con):
404         self.target_template(layout, con)
405
406         row = layout.row(align=True)
407         row.prop(con, "use_x", text="X")
408         row.prop(con, "use_y", text="Y")
409         row.prop(con, "use_z", text="Z")
410
411         layout.prop(con, "use_offset")
412
413         self.space_template(layout, con)
414
415     def MAINTAIN_VOLUME(self, context, layout, con):
416
417         row = layout.row()
418         row.label(text="Free:")
419         row.prop(con, "free_axis", expand=True)
420
421         layout.prop(con, "volume")
422
423         row = layout.row()
424         row.label(text="Convert:")
425         row.prop(con, "owner_space", text="")
426
427     def COPY_TRANSFORMS(self, context, layout, con):
428         self.target_template(layout, con)
429
430         self.space_template(layout, con)
431
432     #def SCRIPT(self, context, layout, con):
433
434     def ACTION(self, context, layout, con):
435         self.target_template(layout, con)
436
437         layout.prop(con, "action")
438
439         layout.prop(con, "transform_channel")
440
441         split = layout.split()
442
443         col = split.column(align=True)
444         col.label(text="Action Length:")
445         col.prop(con, "frame_start", text="Start")
446         col.prop(con, "frame_end", text="End")
447
448         col = split.column(align=True)
449         col.label(text="Target Range:")
450         col.prop(con, "min", text="Min")
451         col.prop(con, "max", text="Max")
452
453         row = layout.row()
454         row.label(text="Convert:")
455         row.prop(con, "target_space", text="")
456
457     def LOCKED_TRACK(self, context, layout, con):
458         self.target_template(layout, con)
459
460         row = layout.row()
461         row.label(text="To:")
462         row.prop(con, "track_axis", expand=True)
463
464         row = layout.row()
465         row.label(text="Lock:")
466         row.prop(con, "lock_axis", expand=True)
467
468     def LIMIT_DISTANCE(self, context, layout, con):
469         self.target_template(layout, con)
470
471         col = layout.column(align=True)
472         col.prop(con, "distance")
473         col.operator("constraint.limitdistance_reset")
474
475         row = layout.row()
476         row.label(text="Clamp Region:")
477         row.prop(con, "limit_mode", text="")
478
479         row = layout.row()
480         row.prop(con, "use_transform_limit")
481         row.label()
482
483     def STRETCH_TO(self, context, layout, con):
484         self.target_template(layout, con)
485
486         row = layout.row()
487         row.prop(con, "rest_length", text="Rest Length")
488         row.operator("constraint.stretchto_reset", text="Reset")
489
490         layout.prop(con, "bulge", text="Volume Variation")
491
492         row = layout.row()
493         row.label(text="Volume:")
494         row.prop(con, "volume", expand=True)
495
496         row.label(text="Plane:")
497         row.prop(con, "keep_axis", expand=True)
498
499     def FLOOR(self, context, layout, con):
500         self.target_template(layout, con)
501
502         row = layout.row()
503         row.prop(con, "use_sticky")
504         row.prop(con, "use_rotation")
505
506         layout.prop(con, "offset")
507
508         row = layout.row()
509         row.label(text="Min/Max:")
510         row.prop(con, "floor_location", expand=True)
511
512         self.space_template(layout, con)
513
514     def RIGID_BODY_JOINT(self, context, layout, con):
515         self.target_template(layout, con, subtargets=False)
516
517         layout.prop(con, "pivot_type")
518         layout.prop(con, "child")
519
520         row = layout.row()
521         row.prop(con, "use_linked_collision", text="Linked Collision")
522         row.prop(con, "show_pivot", text="Display Pivot")
523
524         split = layout.split()
525
526         col = split.column(align=True)
527         col.label(text="Pivot:")
528         col.prop(con, "pivot_x", text="X")
529         col.prop(con, "pivot_y", text="Y")
530         col.prop(con, "pivot_z", text="Z")
531
532         col = split.column(align=True)
533         col.label(text="Axis:")
534         col.prop(con, "axis_x", text="X")
535         col.prop(con, "axis_y", text="Y")
536         col.prop(con, "axis_z", text="Z")
537
538         if con.pivot_type == 'CONE_TWIST':
539             layout.label(text="Limits:")
540             split = layout.split()
541
542             col = split.column()
543             col.prop(con, "use_angular_limit_x", text="Angle X")
544             sub = col.column()
545             sub.active = con.use_angular_limit_x
546             sub.prop(con, "limit_angle_max_x", text="")
547
548             col = split.column()
549             col.prop(con, "use_angular_limit_y", text="Angle Y")
550             sub = col.column()
551             sub.active = con.use_angular_limit_y
552             sub.prop(con, "limit_angle_max_y", text="")
553
554             col = split.column()
555             col.prop(con, "use_angular_limit_z", text="Angle Z")
556             sub = col.column()
557             sub.active = con.use_angular_limit_z
558             sub.prop(con, "limit_angle_max_z", text="")
559
560         elif con.pivot_type == 'GENERIC_6_DOF':
561             layout.label(text="Limits:")
562             split = layout.split()
563
564             col = split.column(align=True)
565             col.prop(con, "use_limit_x", text="X")
566             sub = col.column()
567             sub.active = con.use_limit_x
568             sub.prop(con, "limit_min_x", text="Min")
569             sub.prop(con, "limit_max_x", text="Max")
570
571             col = split.column(align=True)
572             col.prop(con, "use_limit_y", text="Y")
573             sub = col.column()
574             sub.active = con.use_limit_y
575             sub.prop(con, "limit_min_y", text="Min")
576             sub.prop(con, "limit_max_y", text="Max")
577
578             col = split.column(align=True)
579             col.prop(con, "use_limit_z", text="Z")
580             sub = col.column()
581             sub.active = con.use_limit_z
582             sub.prop(con, "limit_min_z", text="Min")
583             sub.prop(con, "limit_max_z", text="Max")
584
585             split = layout.split()
586
587             col = split.column(align=True)
588             col.prop(con, "use_angular_limit_x", text="Angle X")
589             sub = col.column()
590             sub.active = con.use_angular_limit_x
591             sub.prop(con, "limit_angle_min_x", text="Min")
592             sub.prop(con, "limit_angle_max_x", text="Max")
593
594             col = split.column(align=True)
595             col.prop(con, "use_angular_limit_y", text="Angle Y")
596             sub = col.column()
597             sub.active = con.use_angular_limit_y
598             sub.prop(con, "limit_angle_min_y", text="Min")
599             sub.prop(con, "limit_angle_max_y", text="Max")
600
601             col = split.column(align=True)
602             col.prop(con, "use_angular_limit_z", text="Angle Z")
603             sub = col.column()
604             sub.active = con.use_angular_limit_z
605             sub.prop(con, "limit_angle_min_z", text="Min")
606             sub.prop(con, "limit_angle_max_z", text="Max")
607
608         elif con.pivot_type == 'HINGE':
609             layout.label(text="Limits:")
610             split = layout.split()
611
612             row = split.row(align=True)
613             col = row.column()
614             col.prop(con, "use_angular_limit_x", text="Angle X")
615
616             col = row.column()
617             col.active = con.use_angular_limit_x
618             col.prop(con, "limit_angle_min_x", text="Min")
619             col = row.column()
620             col.active = con.use_angular_limit_x
621             col.prop(con, "limit_angle_max_x", text="Max")
622
623     def CLAMP_TO(self, context, layout, con):
624         self.target_template(layout, con)
625
626         row = layout.row()
627         row.label(text="Main Axis:")
628         row.prop(con, "main_axis", expand=True)
629
630         layout.prop(con, "use_cyclic")
631
632     def TRANSFORM(self, context, layout, con):
633         self.target_template(layout, con)
634
635         layout.prop(con, "use_motion_extrapolate", text="Extrapolate")
636
637         col = layout.column()
638         col.row().label(text="Source:")
639         col.row().prop(con, "map_from", expand=True)
640
641         split = layout.split()
642
643         sub = split.column(align=True)
644         sub.label(text="X:")
645         sub.prop(con, "from_min_x", text="Min")
646         sub.prop(con, "from_max_x", text="Max")
647
648         sub = split.column(align=True)
649         sub.label(text="Y:")
650         sub.prop(con, "from_min_y", text="Min")
651         sub.prop(con, "from_max_y", text="Max")
652
653         sub = split.column(align=True)
654         sub.label(text="Z:")
655         sub.prop(con, "from_min_z", text="Min")
656         sub.prop(con, "from_max_z", text="Max")
657
658         col = layout.column()
659         row = col.row()
660         row.label(text="Source to Destination Mapping:")
661
662         # note: chr(187) is the ASCII arrow ( >> ). Blender Text Editor can't
663         # open it. Thus we are using the hard-coded value instead.
664         row = col.row()
665         row.prop(con, "map_to_x_from", expand=False, text="")
666         row.label(text=" %s    X" % chr(187))
667
668         row = col.row()
669         row.prop(con, "map_to_y_from", expand=False, text="")
670         row.label(text=" %s    Y" % chr(187))
671
672         row = col.row()
673         row.prop(con, "map_to_z_from", expand=False, text="")
674         row.label(text=" %s    Z" % chr(187))
675
676         split = layout.split()
677
678         col = split.column()
679         col.label(text="Destination:")
680         col.row().prop(con, "map_to", expand=True)
681
682         split = layout.split()
683
684         col = split.column()
685         col.label(text="X:")
686
687         sub = col.column(align=True)
688         sub.prop(con, "to_min_x", text="Min")
689         sub.prop(con, "to_max_x", text="Max")
690
691         col = split.column()
692         col.label(text="Y:")
693
694         sub = col.column(align=True)
695         sub.prop(con, "to_min_y", text="Min")
696         sub.prop(con, "to_max_y", text="Max")
697
698         col = split.column()
699         col.label(text="Z:")
700
701         sub = col.column(align=True)
702         sub.prop(con, "to_min_z", text="Min")
703         sub.prop(con, "to_max_z", text="Max")
704
705         self.space_template(layout, con)
706
707     def SHRINKWRAP(self, context, layout, con):
708         self.target_template(layout, con, False)
709
710         layout.prop(con, "distance")
711         layout.prop(con, "shrinkwrap_type")
712
713         if con.shrinkwrap_type == 'PROJECT':
714             row = layout.row(align=True)
715             row.prop(con, "use_x")
716             row.prop(con, "use_y")
717             row.prop(con, "use_z")
718
719     def DAMPED_TRACK(self, context, layout, con):
720         self.target_template(layout, con)
721
722         row = layout.row()
723         row.label(text="To:")
724         row.prop(con, "track_axis", expand=True)
725
726     def SPLINE_IK(self, context, layout, con):
727         self.target_template(layout, con)
728
729         col = layout.column()
730         col.label(text="Spline Fitting:")
731         col.prop(con, "chain_count")
732         col.prop(con, "use_even_divisions")
733         col.prop(con, "use_chain_offset")
734
735         col = layout.column()
736         col.label(text="Chain Scaling:")
737         col.prop(con, "use_y_stretch")
738         col.prop(con, "xz_scale_mode")
739         col.prop(con, "use_curve_radius")
740
741     def PIVOT(self, context, layout, con):
742         self.target_template(layout, con)
743
744         if con.target:
745             col = layout.column()
746             col.prop(con, "offset", text="Pivot Offset")
747         else:
748             col = layout.column()
749             col.prop(con, "use_relative_location")
750             if con.use_relative_location:
751                 col.prop(con, "offset", text="Relative Pivot Point")
752             else:
753                 col.prop(con, "offset", text="Absolute Pivot Point")
754
755         col = layout.column()
756         col.prop(con, "rotation_range", text="Pivot When")
757
758     @staticmethod
759     def _getConstraintClip(context, con):
760         if not con.use_active_clip:
761             return con.clip
762         else:
763             return context.scene.active_clip
764
765     def FOLLOW_TRACK(self, context, layout, con):
766         clip = self._getConstraintClip(context, con)
767
768         row = layout.row()
769         row.prop(con, "use_active_clip")
770         row.prop(con, "use_3d_position")
771
772         if not con.use_active_clip:
773             layout.prop(con, "clip")
774
775         if clip:
776             layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA')
777             layout.prop_search(con, "track", clip.tracking, "tracks", icon='ANIMATION_DATA')
778
779         layout.prop(con, "camera")
780
781         layout.operator("clip.constraint_to_fcurve")
782
783     def CAMERA_SOLVER(self, context, layout, con):
784         layout.prop(con, "use_active_clip")
785
786         if not con.use_active_clip:
787             layout.prop(con, "clip")
788
789         layout.operator("clip.constraint_to_fcurve")
790
791     def OBJECT_SOLVER(self, context, layout, con):
792         scene = context.scene
793         clip = self._getConstraintClip(context, con)
794
795         layout.prop(con, "use_active_clip")
796
797         if not con.use_active_clip:
798             layout.prop(con, "clip")
799
800         if clip:
801             layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA')
802
803         layout.prop(con, "camera")
804
805         row = layout.row()
806         row.operator("constraint.objectsolver_set_inverse")
807         row.operator("constraint.objectsolver_clear_inverse")
808
809         layout.operator("clip.constraint_to_fcurve")
810
811     def SCRIPT(self, context, layout, con):
812         layout.label("Blender 2.5 has no py-constraints")
813
814
815 class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
816     bl_label = "Object Constraints"
817     bl_context = "constraint"
818
819     @classmethod
820     def poll(cls, context):
821         return (context.object)
822
823     def draw(self, context):
824         layout = self.layout
825
826         ob = context.object
827
828         if ob.mode == 'POSE':
829             box = layout.box()
830             box.alert = True
831             box.label(icon='INFO', text="See Bone Constraints tab to Add Constraints to active bone")
832         else:
833             layout.operator_menu_enum("object.constraint_add", "type")
834
835         for con in ob.constraints:
836             self.draw_constraint(context, con)
837
838
839 class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
840     bl_label = "Bone Constraints"
841     bl_context = "bone_constraint"
842
843     @classmethod
844     def poll(cls, context):
845         return (context.pose_bone)
846
847     def draw(self, context):
848         layout = self.layout
849
850         layout.operator_menu_enum("pose.constraint_add", "type")
851
852         for con in context.pose_bone.constraints:
853             self.draw_constraint(context, con)
854
855 if __name__ == "__main__":  # only for live edit.
856     bpy.utils.register_module(__name__)