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