Merging pepper to trunk at revision 39791.
[blender-staging.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
239         split = layout.split()
240
241         col = split.column(align=True)
242         col.prop(con, "use_limit_x")
243         sub = col.column()
244         sub.active = con.use_limit_x
245         sub.prop(con, "min_x", text="Min")
246         sub.prop(con, "max_x", text="Max")
247
248         col = split.column(align=True)
249         col.prop(con, "use_limit_y")
250         sub = col.column()
251         sub.active = con.use_limit_y
252         sub.prop(con, "min_y", text="Min")
253         sub.prop(con, "max_y", text="Max")
254
255         col = split.column(align=True)
256         col.prop(con, "use_limit_z")
257         sub = col.column()
258         sub.active = con.use_limit_z
259         sub.prop(con, "min_z", text="Min")
260         sub.prop(con, "max_z", text="Max")
261
262         row = layout.row()
263         row.prop(con, "use_transform_limit")
264         row.label()
265
266         row = layout.row()
267         row.label(text="Convert:")
268         row.prop(con, "owner_space", text="")
269
270     def LIMIT_LOCATION(self, context, layout, con):
271         split = layout.split()
272
273         col = split.column()
274         col.prop(con, "use_min_x")
275         sub = col.column()
276         sub.active = con.use_min_x
277         sub.prop(con, "min_x", text="")
278         col.prop(con, "use_max_x")
279         sub = col.column()
280         sub.active = con.use_max_x
281         sub.prop(con, "max_x", text="")
282
283         col = split.column()
284         col.prop(con, "use_min_y")
285         sub = col.column()
286         sub.active = con.use_min_y
287         sub.prop(con, "min_y", text="")
288         col.prop(con, "use_max_y")
289         sub = col.column()
290         sub.active = con.use_max_y
291         sub.prop(con, "max_y", text="")
292
293         col = split.column()
294         col.prop(con, "use_min_z")
295         sub = col.column()
296         sub.active = con.use_min_z
297         sub.prop(con, "min_z", text="")
298         col.prop(con, "use_max_z")
299         sub = col.column()
300         sub.active = con.use_max_z
301         sub.prop(con, "max_z", text="")
302
303         row = layout.row()
304         row.prop(con, "use_transform_limit")
305         row.label()
306
307         row = layout.row()
308         row.label(text="Convert:")
309         row.prop(con, "owner_space", text="")
310
311     def LIMIT_SCALE(self, context, layout, con):
312         split = layout.split()
313
314         col = split.column()
315         col.prop(con, "use_min_x")
316         sub = col.column()
317         sub.active = con.use_min_x
318         sub.prop(con, "min_x", text="")
319         col.prop(con, "use_max_x")
320         sub = col.column()
321         sub.active = con.use_max_x
322         sub.prop(con, "max_x", text="")
323
324         col = split.column()
325         col.prop(con, "use_min_y")
326         sub = col.column()
327         sub.active = con.use_min_y
328         sub.prop(con, "min_y", text="")
329         col.prop(con, "use_max_y")
330         sub = col.column()
331         sub.active = con.use_max_y
332         sub.prop(con, "max_y", text="")
333
334         col = split.column()
335         col.prop(con, "use_min_z")
336         sub = col.column()
337         sub.active = con.use_min_z
338         sub.prop(con, "min_z", text="")
339         col.prop(con, "use_max_z")
340         sub = col.column()
341         sub.active = con.use_max_z
342         sub.prop(con, "max_z", text="")
343
344         row = layout.row()
345         row.prop(con, "use_transform_limit")
346         row.label()
347
348         row = layout.row()
349         row.label(text="Convert:")
350         row.prop(con, "owner_space", text="")
351
352     def COPY_ROTATION(self, context, layout, con):
353         self.target_template(layout, con)
354
355         split = layout.split()
356
357         col = split.column()
358         col.prop(con, "use_x", text="X")
359         sub = col.column()
360         sub.active = con.use_x
361         sub.prop(con, "invert_x", text="Invert")
362
363         col = split.column()
364         col.prop(con, "use_y", text="Y")
365         sub = col.column()
366         sub.active = con.use_y
367         sub.prop(con, "invert_y", text="Invert")
368
369         col = split.column()
370         col.prop(con, "use_z", text="Z")
371         sub = col.column()
372         sub.active = con.use_z
373         sub.prop(con, "invert_z", text="Invert")
374
375         layout.prop(con, "use_offset")
376
377         self.space_template(layout, con)
378
379     def COPY_LOCATION(self, context, layout, con):
380         self.target_template(layout, con)
381
382         split = layout.split()
383
384         col = split.column()
385         col.prop(con, "use_x", text="X")
386         sub = col.column()
387         sub.active = con.use_x
388         sub.prop(con, "invert_x", text="Invert")
389
390         col = split.column()
391         col.prop(con, "use_y", text="Y")
392         sub = col.column()
393         sub.active = con.use_y
394         sub.prop(con, "invert_y", text="Invert")
395
396         col = split.column()
397         col.prop(con, "use_z", text="Z")
398         sub = col.column()
399         sub.active = con.use_z
400         sub.prop(con, "invert_z", text="Invert")
401
402         layout.prop(con, "use_offset")
403
404         self.space_template(layout, con)
405
406     def COPY_SCALE(self, context, layout, con):
407         self.target_template(layout, con)
408
409         row = layout.row(align=True)
410         row.prop(con, "use_x", text="X")
411         row.prop(con, "use_y", text="Y")
412         row.prop(con, "use_z", text="Z")
413
414         layout.prop(con, "use_offset")
415
416         self.space_template(layout, con)
417
418     def MAINTAIN_VOLUME(self, context, layout, con):
419
420         row = layout.row()
421         row.label(text="Free:")
422         row.prop(con, "free_axis", expand=True)
423
424         layout.prop(con, "volume")
425
426         self.space_template(layout, con)
427
428     def COPY_TRANSFORMS(self, context, layout, con):
429         self.target_template(layout, con)
430
431         self.space_template(layout, con)
432
433     #def SCRIPT(self, context, layout, con):
434
435     def ACTION(self, context, layout, con):
436         self.target_template(layout, con)
437
438         layout.prop(con, "action")
439
440         layout.prop(con, "transform_channel")
441
442         split = layout.split()
443
444         col = split.column(align=True)
445         col.label(text="Action Length:")
446         col.prop(con, "frame_start", text="Start")
447         col.prop(con, "frame_end", text="End")
448
449         col = split.column(align=True)
450         col.label(text="Target Range:")
451         col.prop(con, "min", text="Min")
452         col.prop(con, "max", text="Max")
453
454         row = layout.row()
455         row.label(text="Convert:")
456         row.prop(con, "target_space", text="")
457
458     def LOCKED_TRACK(self, context, layout, con):
459         self.target_template(layout, con)
460
461         row = layout.row()
462         row.label(text="To:")
463         row.prop(con, "track_axis", expand=True)
464
465         row = layout.row()
466         row.label(text="Lock:")
467         row.prop(con, "lock_axis", expand=True)
468
469     def LIMIT_DISTANCE(self, context, layout, con):
470         self.target_template(layout, con)
471
472         col = layout.column(align=True)
473         col.prop(con, "distance")
474         col.operator("constraint.limitdistance_reset")
475
476         row = layout.row()
477         row.label(text="Clamp Region:")
478         row.prop(con, "limit_mode", text="")
479
480         row = layout.row()
481         row.prop(con, "use_transform_limit")
482         row.label()
483
484
485     def STRETCH_TO(self, context, layout, con):
486         self.target_template(layout, con)
487
488         row = layout.row()
489         row.prop(con, "rest_length", text="Rest Length")
490         row.operator("constraint.stretchto_reset", text="Reset")
491
492         layout.prop(con, "bulge", text="Volume Variation")
493
494         row = layout.row()
495         row.label(text="Volume:")
496         row.prop(con, "volume", expand=True)
497
498         row.label(text="Plane:")
499         row.prop(con, "keep_axis", expand=True)
500
501     def FLOOR(self, context, layout, con):
502         self.target_template(layout, con)
503
504         row = layout.row()
505         row.prop(con, "use_sticky")
506         row.prop(con, "use_rotation")
507
508         layout.prop(con, "offset")
509
510         row = layout.row()
511         row.label(text="Min/Max:")
512         row.prop(con, "floor_location", expand=True)
513
514         self.space_template(layout, con)
515
516     def RIGID_BODY_JOINT(self, context, layout, con):
517         self.target_template(layout, con, subtargets=False)
518
519         layout.prop(con, "pivot_type")
520         layout.prop(con, "child")
521
522         row = layout.row()
523         row.prop(con, "use_linked_collision", text="Linked Collision")
524         row.prop(con, "show_pivot", text="Display Pivot")
525
526         split = layout.split()
527
528         col = split.column(align=True)
529         col.label(text="Pivot:")
530         col.prop(con, "pivot_x", text="X")
531         col.prop(con, "pivot_y", text="Y")
532         col.prop(con, "pivot_z", text="Z")
533
534         col = split.column(align=True)
535         col.label(text="Axis:")
536         col.prop(con, "axis_x", text="X")
537         col.prop(con, "axis_y", text="Y")
538         col.prop(con, "axis_z", text="Z")
539
540         if con.pivot_type == 'CONE_TWIST':
541             layout.label(text="Limits:")
542             split = layout.split()
543
544             col = split.column()
545             col.prop(con, "use_angular_limit_x", text="Angle X")
546             sub = col.column()
547             sub.active = con.use_angular_limit_x
548             sub.prop(con, "limit_angle_max_x", text="")
549
550             col = split.column()
551             col.prop(con, "use_angular_limit_y", text="Angle Y")
552             sub = col.column()
553             sub.active = con.use_angular_limit_y
554             sub.prop(con, "limit_angle_max_y", text="")
555
556             col = split.column()
557             col.prop(con, "use_angular_limit_z", text="Angle Z")
558             sub = col.column()
559             sub.active = con.use_angular_limit_z
560             sub.prop(con, "limit_angle_max_z", text="")
561
562         elif con.pivot_type == 'GENERIC_6_DOF':
563             layout.label(text="Limits:")
564             split = layout.split()
565
566             col = split.column(align=True)
567             col.prop(con, "use_limit_x", text="X")
568             sub = col.column()
569             sub.active = con.use_limit_x
570             sub.prop(con, "limit_min_x", text="Min")
571             sub.prop(con, "limit_max_x", text="Max")
572
573             col = split.column(align=True)
574             col.prop(con, "use_limit_y", text="Y")
575             sub = col.column()
576             sub.active = con.use_limit_y
577             sub.prop(con, "limit_min_y", text="Min")
578             sub.prop(con, "limit_max_y", text="Max")
579
580             col = split.column(align=True)
581             col.prop(con, "use_limit_z", text="Z")
582             sub = col.column()
583             sub.active = con.use_limit_z
584             sub.prop(con, "limit_min_z", text="Min")
585             sub.prop(con, "limit_max_z", text="Max")
586
587             split = layout.split()
588
589             col = split.column(align=True)
590             col.prop(con, "use_angular_limit_x", text="Angle X")
591             sub = col.column()
592             sub.active = con.use_angular_limit_x
593             sub.prop(con, "limit_angle_min_x", text="Min")
594             sub.prop(con, "limit_angle_max_x", text="Max")
595
596             col = split.column(align=True)
597             col.prop(con, "use_angular_limit_y", text="Angle Y")
598             sub = col.column()
599             sub.active = con.use_angular_limit_y
600             sub.prop(con, "limit_angle_min_y", text="Min")
601             sub.prop(con, "limit_angle_max_y", text="Max")
602
603             col = split.column(align=True)
604             col.prop(con, "use_angular_limit_z", text="Angle Z")
605             sub = col.column()
606             sub.active = con.use_angular_limit_z
607             sub.prop(con, "limit_angle_min_z", text="Min")
608             sub.prop(con, "limit_angle_max_z", text="Max")
609
610         elif con.pivot_type == 'HINGE':
611             layout.label(text="Limits:")
612             split = layout.split()
613
614             row = split.row(align=True)
615             col = row.column()
616             col.prop(con, "use_angular_limit_x", text="Angle X")
617
618             col = row.column()
619             col.active = con.use_angular_limit_x
620             col.prop(con, "limit_angle_min_x", text="Min")
621             col = row.column()
622             col.active = con.use_angular_limit_x
623             col.prop(con, "limit_angle_max_x", text="Max")
624
625     def CLAMP_TO(self, context, layout, con):
626         self.target_template(layout, con)
627
628         row = layout.row()
629         row.label(text="Main Axis:")
630         row.prop(con, "main_axis", expand=True)
631
632         layout.prop(con, "use_cyclic")
633
634     def TRANSFORM(self, context, layout, con):
635         self.target_template(layout, con)
636
637         layout.prop(con, "use_motion_extrapolate", text="Extrapolate")
638
639         col = layout.column()
640         col.row().label(text="Source:")
641         col.row().prop(con, "map_from", expand=True)
642
643         split = layout.split()
644
645         sub = split.column(align=True)
646         sub.label(text="X:")
647         sub.prop(con, "from_min_x", text="Min")
648         sub.prop(con, "from_max_x", text="Max")
649
650         sub = split.column(align=True)
651         sub.label(text="Y:")
652         sub.prop(con, "from_min_y", text="Min")
653         sub.prop(con, "from_max_y", text="Max")
654
655         sub = split.column(align=True)
656         sub.label(text="Z:")
657         sub.prop(con, "from_min_z", text="Min")
658         sub.prop(con, "from_max_z", text="Max")
659
660         col = layout.column()
661         row = col.row()
662         row.label(text="Source to Destination Mapping:")
663
664         # note: chr(187) is the ASCII arrow ( >> ). Blender Text Editor can't
665         # open it. Thus we are using the hardcoded value instead.
666         row = col.row()
667         row.prop(con, "map_to_x_from", expand=False, text="")
668         row.label(text=" %s    X" % chr(187))
669
670         row = col.row()
671         row.prop(con, "map_to_y_from", expand=False, text="")
672         row.label(text=" %s    Y" % chr(187))
673
674         row = col.row()
675         row.prop(con, "map_to_z_from", expand=False, text="")
676         row.label(text=" %s    Z" % chr(187))
677
678         split = layout.split()
679
680         col = split.column()
681         col.label(text="Destination:")
682         col.row().prop(con, "map_to", expand=True)
683
684         split = layout.split()
685
686         col = split.column()
687         col.label(text="X:")
688
689         sub = col.column(align=True)
690         sub.prop(con, "to_min_x", text="Min")
691         sub.prop(con, "to_max_x", text="Max")
692
693         col = split.column()
694         col.label(text="Y:")
695
696         sub = col.column(align=True)
697         sub.prop(con, "to_min_y", text="Min")
698         sub.prop(con, "to_max_y", text="Max")
699
700         col = split.column()
701         col.label(text="Z:")
702
703         sub = col.column(align=True)
704         sub.prop(con, "to_min_z", text="Min")
705         sub.prop(con, "to_max_z", text="Max")
706
707         self.space_template(layout, con)
708
709     def SHRINKWRAP(self, context, layout, con):
710         self.target_template(layout, con, False)
711
712         layout.prop(con, "distance")
713         layout.prop(con, "shrinkwrap_type")
714
715         if con.shrinkwrap_type == 'PROJECT':
716             row = layout.row(align=True)
717             row.prop(con, "use_x")
718             row.prop(con, "use_y")
719             row.prop(con, "use_z")
720
721     def DAMPED_TRACK(self, context, layout, con):
722         self.target_template(layout, con)
723
724         row = layout.row()
725         row.label(text="To:")
726         row.prop(con, "track_axis", expand=True)
727
728     def SPLINE_IK(self, context, layout, con):
729         self.target_template(layout, con)
730
731         col = layout.column()
732         col.label(text="Spline Fitting:")
733         col.prop(con, "chain_count")
734         col.prop(con, "use_even_divisions")
735         col.prop(con, "use_chain_offset")
736
737         col = layout.column()
738         col.label(text="Chain Scaling:")
739         col.prop(con, "use_y_stretch")
740         col.prop(con, "xz_scale_mode")
741         col.prop(con, "use_curve_radius")
742
743     def PIVOT(self, context, layout, con):
744         self.target_template(layout, con)
745
746         if con.target:
747             col = layout.column()
748             col.prop(con, "offset", text="Pivot Offset")
749         else:
750             col = layout.column()
751             col.prop(con, "use_relative_location")
752             if con.use_relative_location:
753                 col.prop(con, "offset", text="Relative Pivot Point")
754             else:
755                 col.prop(con, "offset", text="Absolute Pivot Point")
756
757         col = layout.column()
758         col.prop(con, "rotation_range", text="Pivot When")
759
760     def SCRIPT(self, context, layout, con):
761         layout.label("Blender 2.5 has no py-constraints")
762
763
764 class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
765     bl_label = "Object Constraints"
766     bl_context = "constraint"
767
768     @classmethod
769     def poll(cls, context):
770         return (context.object)
771
772     def draw(self, context):
773         layout = self.layout
774
775         ob = context.object
776
777         if ob.mode == 'POSE':
778             box = layout.box()
779             box.alert = True
780             box.label(icon='INFO', text="See Bone Constraints tab to Add Constraints to active bone")
781         else:
782             layout.operator_menu_enum("object.constraint_add", "type")
783
784         for con in ob.constraints:
785             self.draw_constraint(context, con)
786
787
788 class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
789     bl_label = "Bone Constraints"
790     bl_context = "bone_constraint"
791
792     @classmethod
793     def poll(cls, context):
794         return (context.pose_bone)
795
796     def draw(self, context):
797         layout = self.layout
798
799         layout.operator_menu_enum("pose.constraint_add", "type")
800
801         for con in context.pose_bone.constraints:
802             self.draw_constraint(context, con)
803
804 if __name__ == "__main__":  # only for live edit.
805     bpy.utils.register_module(__name__)