2.5 UI Files:
[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         self.space_template(layout, con)
424
425     def COPY_TRANSFORMS(self, context, layout, con):
426         self.target_template(layout, con)
427
428         self.space_template(layout, con)
429
430     #def SCRIPT(self, context, layout, con):
431
432     def ACTION(self, context, layout, con):
433         self.target_template(layout, con)
434
435         layout.prop(con, "action")
436
437         layout.prop(con, "transform_channel")
438
439         split = layout.split()
440
441         col = split.column(align=True)
442         col.label(text="Action Length:")
443         col.prop(con, "frame_start", text="Start")
444         col.prop(con, "frame_end", text="End")
445
446         col = split.column(align=True)
447         col.label(text="Target Range:")
448         col.prop(con, "min", text="Min")
449         col.prop(con, "max", text="Max")
450
451         row = layout.row()
452         row.label(text="Convert:")
453         row.prop(con, "target_space", text="")
454
455     def LOCKED_TRACK(self, context, layout, con):
456         self.target_template(layout, con)
457
458         row = layout.row()
459         row.label(text="To:")
460         row.prop(con, "track_axis", expand=True)
461
462         row = layout.row()
463         row.label(text="Lock:")
464         row.prop(con, "lock_axis", expand=True)
465
466     def LIMIT_DISTANCE(self, context, layout, con):
467         self.target_template(layout, con)
468
469         col = layout.column(align=True)
470         col.prop(con, "distance")
471         col.operator("constraint.limitdistance_reset")
472
473         row = layout.row()
474         row.label(text="Clamp Region:")
475         row.prop(con, "limit_mode", text="")
476
477         row = layout.row()
478         row.prop(con, "use_transform_limit")
479         row.label()
480
481
482     def STRETCH_TO(self, context, layout, con):
483         self.target_template(layout, con)
484
485         row = layout.row()
486         row.prop(con, "rest_length", text="Rest Length")
487         row.operator("constraint.stretchto_reset", text="Reset")
488
489         layout.prop(con, "bulge", text="Volume Variation")
490
491         row = layout.row()
492         row.label(text="Volume:")
493         row.prop(con, "volume", expand=True)
494
495         row.label(text="Plane:")
496         row.prop(con, "keep_axis", expand=True)
497
498     def FLOOR(self, context, layout, con):
499         self.target_template(layout, con)
500
501         row = layout.row()
502         row.prop(con, "use_sticky")
503         row.prop(con, "use_rotation")
504
505         layout.prop(con, "offset")
506
507         row = layout.row()
508         row.label(text="Min/Max:")
509         row.prop(con, "floor_location", expand=True)
510
511         self.space_template(layout, con)
512
513     def RIGID_BODY_JOINT(self, context, layout, con):
514         self.target_template(layout, con, subtargets=False)
515
516         layout.prop(con, "pivot_type")
517         layout.prop(con, "child")
518
519         row = layout.row()
520         row.prop(con, "use_linked_collision", text="Linked Collision")
521         row.prop(con, "show_pivot", text="Display Pivot")
522
523         split = layout.split()
524
525         col = split.column(align=True)
526         col.label(text="Pivot:")
527         col.prop(con, "pivot_x", text="X")
528         col.prop(con, "pivot_y", text="Y")
529         col.prop(con, "pivot_z", text="Z")
530
531         col = split.column(align=True)
532         col.label(text="Axis:")
533         col.prop(con, "axis_x", text="X")
534         col.prop(con, "axis_y", text="Y")
535         col.prop(con, "axis_z", text="Z")
536
537         if con.pivot_type == 'CONE_TWIST':
538             layout.label(text="Limits:")
539             split = layout.split()
540
541             col = split.column()
542             col.prop(con, "use_angular_limit_x", text="Angle X")
543             sub = col.column()
544             sub.active = con.use_angular_limit_x
545             sub.prop(con, "limit_angle_max_x", text="")
546
547             col = split.column()
548             col.prop(con, "use_angular_limit_y", text="Angle Y")
549             sub = col.column()
550             sub.active = con.use_angular_limit_y
551             sub.prop(con, "limit_angle_max_y", text="")
552
553             col = split.column()
554             col.prop(con, "use_angular_limit_z", text="Angle Z")
555             sub = col.column()
556             sub.active = con.use_angular_limit_z
557             sub.prop(con, "limit_angle_max_z", text="")
558
559         elif con.pivot_type == 'GENERIC_6_DOF':
560             layout.label(text="Limits:")
561             split = layout.split()
562
563             col = split.column(align=True)
564             col.prop(con, "use_limit_x", text="X")
565             sub = col.column()
566             sub.active = con.use_limit_x
567             sub.prop(con, "limit_min_x", text="Min")
568             sub.prop(con, "limit_max_x", text="Max")
569
570             col = split.column(align=True)
571             col.prop(con, "use_limit_y", text="Y")
572             sub = col.column()
573             sub.active = con.use_limit_y
574             sub.prop(con, "limit_min_y", text="Min")
575             sub.prop(con, "limit_max_y", text="Max")
576
577             col = split.column(align=True)
578             col.prop(con, "use_limit_z", text="Z")
579             sub = col.column()
580             sub.active = con.use_limit_z
581             sub.prop(con, "limit_min_z", text="Min")
582             sub.prop(con, "limit_max_z", text="Max")
583
584             split = layout.split()
585
586             col = split.column(align=True)
587             col.prop(con, "use_angular_limit_x", text="Angle X")
588             sub = col.column()
589             sub.active = con.use_angular_limit_x
590             sub.prop(con, "limit_angle_min_x", text="Min")
591             sub.prop(con, "limit_angle_max_x", text="Max")
592
593             col = split.column(align=True)
594             col.prop(con, "use_angular_limit_y", text="Angle Y")
595             sub = col.column()
596             sub.active = con.use_angular_limit_y
597             sub.prop(con, "limit_angle_min_y", text="Min")
598             sub.prop(con, "limit_angle_max_y", text="Max")
599
600             col = split.column(align=True)
601             col.prop(con, "use_angular_limit_z", text="Angle Z")
602             sub = col.column()
603             sub.active = con.use_angular_limit_z
604             sub.prop(con, "limit_angle_min_z", text="Min")
605             sub.prop(con, "limit_angle_max_z", text="Max")
606
607         elif con.pivot_type == 'HINGE':
608             layout.label(text="Limits:")
609             split = layout.split()
610
611             row = split.row(align=True)
612             col = row.column()
613             col.prop(con, "use_angular_limit_x", text="Angle X")
614
615             col = row.column()
616             col.active = con.use_angular_limit_x
617             col.prop(con, "limit_angle_min_x", text="Min")
618             col = row.column()
619             col.active = con.use_angular_limit_x
620             col.prop(con, "limit_angle_max_x", text="Max")
621
622     def CLAMP_TO(self, context, layout, con):
623         self.target_template(layout, con)
624
625         row = layout.row()
626         row.label(text="Main Axis:")
627         row.prop(con, "main_axis", expand=True)
628
629         layout.prop(con, "use_cyclic")
630
631     def TRANSFORM(self, context, layout, con):
632         self.target_template(layout, con)
633
634         layout.prop(con, "use_motion_extrapolate", text="Extrapolate")
635
636         col = layout.column()
637         col.row().label(text="Source:")
638         col.row().prop(con, "map_from", expand=True)
639
640         split = layout.split()
641
642         sub = split.column(align=True)
643         sub.label(text="X:")
644         sub.prop(con, "from_min_x", text="Min")
645         sub.prop(con, "from_max_x", text="Max")
646
647         sub = split.column(align=True)
648         sub.label(text="Y:")
649         sub.prop(con, "from_min_y", text="Min")
650         sub.prop(con, "from_max_y", text="Max")
651
652         sub = split.column(align=True)
653         sub.label(text="Z:")
654         sub.prop(con, "from_min_z", text="Min")
655         sub.prop(con, "from_max_z", text="Max")
656
657         col = layout.column()
658         row = col.row()
659         row.label(text="Source to Destination Mapping:")
660
661         # note: chr(187) is the ASCII arrow ( >> ). Blender Text Editor can't
662         # open it. Thus we are using the hardcoded value instead.
663         row = col.row()
664         row.prop(con, "map_to_x_from", expand=False, text="")
665         row.label(text=" %s    X" % chr(187))
666
667         row = col.row()
668         row.prop(con, "map_to_y_from", expand=False, text="")
669         row.label(text=" %s    Y" % chr(187))
670
671         row = col.row()
672         row.prop(con, "map_to_z_from", expand=False, text="")
673         row.label(text=" %s    Z" % chr(187))
674
675         split = layout.split()
676
677         col = split.column()
678         col.label(text="Destination:")
679         col.row().prop(con, "map_to", expand=True)
680
681         split = layout.split()
682
683         col = split.column()
684         col.label(text="X:")
685
686         sub = col.column(align=True)
687         sub.prop(con, "to_min_x", text="Min")
688         sub.prop(con, "to_max_x", text="Max")
689
690         col = split.column()
691         col.label(text="Y:")
692
693         sub = col.column(align=True)
694         sub.prop(con, "to_min_y", text="Min")
695         sub.prop(con, "to_max_y", text="Max")
696
697         col = split.column()
698         col.label(text="Z:")
699
700         sub = col.column(align=True)
701         sub.prop(con, "to_min_z", text="Min")
702         sub.prop(con, "to_max_z", text="Max")
703
704         self.space_template(layout, con)
705
706     def SHRINKWRAP(self, context, layout, con):
707         self.target_template(layout, con, False)
708
709         layout.prop(con, "distance")
710         layout.prop(con, "shrinkwrap_type")
711
712         if con.shrinkwrap_type == 'PROJECT':
713             row = layout.row(align=True)
714             row.prop(con, "use_x")
715             row.prop(con, "use_y")
716             row.prop(con, "use_z")
717
718     def DAMPED_TRACK(self, context, layout, con):
719         self.target_template(layout, con)
720
721         row = layout.row()
722         row.label(text="To:")
723         row.prop(con, "track_axis", expand=True)
724
725     def SPLINE_IK(self, context, layout, con):
726         self.target_template(layout, con)
727
728         col = layout.column()
729         col.label(text="Spline Fitting:")
730         col.prop(con, "chain_count")
731         col.prop(con, "use_even_divisions")
732         col.prop(con, "use_chain_offset")
733
734         col = layout.column()
735         col.label(text="Chain Scaling:")
736         col.prop(con, "use_y_stretch")
737         col.prop(con, "xz_scale_mode")
738         col.prop(con, "use_curve_radius")
739
740     def PIVOT(self, context, layout, con):
741         self.target_template(layout, con)
742
743         if con.target:
744             col = layout.column()
745             col.prop(con, "offset", text="Pivot Offset")
746         else:
747             col = layout.column()
748             col.prop(con, "use_relative_location")
749             if con.use_relative_location:
750                 col.prop(con, "offset", text="Relative Pivot Point")
751             else:
752                 col.prop(con, "offset", text="Absolute Pivot Point")
753
754         col = layout.column()
755         col.prop(con, "rotation_range", text="Pivot When")
756
757     def SCRIPT(self, context, layout, con):
758         layout.label("Blender 2.5 has no py-constraints")
759
760
761 class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
762     bl_label = "Object Constraints"
763     bl_context = "constraint"
764
765     @classmethod
766     def poll(cls, context):
767         return (context.object)
768
769     def draw(self, context):
770         layout = self.layout
771
772         ob = context.object
773
774         if ob.mode == 'POSE':
775             box = layout.box()
776             box.alert = True
777             box.label(icon='INFO', text="See Bone Constraints tab to Add Constraints to active bone")
778         else:
779             layout.operator_menu_enum("object.constraint_add", "type")
780
781         for con in ob.constraints:
782             self.draw_constraint(context, con)
783
784
785 class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
786     bl_label = "Bone Constraints"
787     bl_context = "bone_constraint"
788
789     @classmethod
790     def poll(cls, context):
791         return (context.pose_bone)
792
793     def draw(self, context):
794         layout = self.layout
795
796         layout.operator_menu_enum("pose.constraint_add", "type")
797
798         for con in context.pose_bone.constraints:
799             self.draw_constraint(context, con)
800
801 if __name__ == "__main__":  # only for live edit.
802     bpy.utils.register_module(__name__)