merge from trunk #37722
[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
22
23 class ConstraintButtonsPanel():
24     bl_space_type = 'PROPERTIES'
25     bl_region_type = 'WINDOW'
26     bl_context = "constraint"
27
28     def draw_constraint(self, context, con):
29         layout = self.layout
30
31         box = layout.template_constraint(con)
32
33         if box:
34             # match enum type to our functions, avoids a lookup table.
35             getattr(self, con.type)(context, box, con)
36
37             if con.type not in {'RIGID_BODY_JOINT', 'NULL'}:
38                 box.prop(con, "influence")
39
40     def space_template(self, layout, con, target=True, owner=True):
41         if target or owner:
42
43             split = layout.split(percentage=0.2)
44
45             split.label(text="Space:")
46             row = split.row()
47
48             if target:
49                 row.prop(con, "target_space", text="")
50
51             if target and owner:
52                 row.label(icon='ARROW_LEFTRIGHT')
53
54             if owner:
55                 row.prop(con, "owner_space", text="")
56
57     def target_template(self, layout, con, subtargets=True):
58         layout.prop(con, "target")  # XXX limiting settings for only 'curves' or some type of object
59
60         if con.target and subtargets:
61             if con.target.type == 'ARMATURE':
62                 layout.prop_search(con, "subtarget", con.target.data, "bones", text="Bone")
63
64                 if hasattr(con, "head_tail"):
65                     row = layout.row()
66                     row.label(text="Head/Tail:")
67                     row.prop(con, "head_tail", text="")
68             elif con.target.type in {'MESH', 'LATTICE'}:
69                 layout.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
70
71     def ik_template(self, layout, con):
72         # only used for iTaSC
73         layout.prop(con, "pole_target")
74
75         if con.pole_target and con.pole_target.type == 'ARMATURE':
76             layout.prop_search(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
77
78         if con.pole_target:
79             row = layout.row()
80             row.label()
81             row.prop(con, "pole_angle")
82
83         split = layout.split(percentage=0.33)
84         col = split.column()
85         col.prop(con, "use_tail")
86         col.prop(con, "use_stretch")
87
88         col = split.column()
89         col.prop(con, "chain_count")
90         col.prop(con, "use_target")
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             # Legacy 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.label(text="Weight:")
155             col.prop(con, "weight", text="Position", slider=True)
156             sub = col.column()
157             sub.active = con.use_rotation
158             sub.prop(con, "orient_weight", text="Rotation", slider=True)
159
160             col = split.column()
161             col.prop(con, "use_tail")
162             col.prop(con, "use_stretch")
163             col.separator()
164             col.prop(con, "use_target")
165             col.prop(con, "use_rotation")
166
167     def IK_COPY_POSE(self, context, layout, con):
168         self.target_template(layout, con)
169         self.ik_template(layout, con)
170
171         row = layout.row()
172         row.label(text="Axis Ref:")
173         row.prop(con, "reference_axis", expand=True)
174         split = layout.split(percentage=0.33)
175         split.row().prop(con, "use_location")
176         row = split.row()
177         row.prop(con, "weight", text="Weight", slider=True)
178         row.active = con.use_location
179         split = layout.split(percentage=0.33)
180         row = split.row()
181         row.label(text="Lock:")
182         row = split.row()
183         row.prop(con, "lock_location_x", text="X")
184         row.prop(con, "lock_location_y", text="Y")
185         row.prop(con, "lock_location_z", text="Z")
186         split.active = con.use_location
187
188         split = layout.split(percentage=0.33)
189         split.row().prop(con, "use_rotation")
190         row = split.row()
191         row.prop(con, "orient_weight", text="Weight", slider=True)
192         row.active = con.use_rotation
193         split = layout.split(percentage=0.33)
194         row = split.row()
195         row.label(text="Lock:")
196         row = split.row()
197         row.prop(con, "lock_rotation_x", text="X")
198         row.prop(con, "lock_rotation_y", text="Y")
199         row.prop(con, "lock_rotation_z", text="Z")
200         split.active = con.use_rotation
201
202     def IK_DISTANCE(self, context, layout, con):
203         self.target_template(layout, con)
204         self.ik_template(layout, con)
205
206         layout.prop(con, "limit_mode")
207
208         row = layout.row()
209         row.prop(con, "weight", text="Weight", slider=True)
210         row.prop(con, "distance", text="Distance", slider=True)
211
212     def FOLLOW_PATH(self, context, layout, con):
213         self.target_template(layout, con)
214
215         split = layout.split()
216
217         col = split.column()
218         col.prop(con, "use_curve_follow")
219         col.prop(con, "use_curve_radius")
220
221         col = split.column()
222         col.prop(con, "use_fixed_location")
223         if con.use_fixed_location:
224             col.prop(con, "offset_factor", text="Offset")
225         else:
226             col.prop(con, "offset")
227
228         row = layout.row()
229         row.label(text="Forward:")
230         row.prop(con, "forward_axis", expand=True)
231
232         row = layout.row()
233         row.prop(con, "up_axis", text="Up")
234         row.label()
235
236     def LIMIT_ROTATION(self, context, layout, con):
237
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         row = layout.row()
262         row.prop(con, "use_transform_limit")
263         row.label()
264
265         row = layout.row()
266         row.label(text="Convert:")
267         row.prop(con, "owner_space", text="")
268
269     def LIMIT_LOCATION(self, context, layout, con):
270         split = layout.split()
271
272         col = split.column()
273         col.prop(con, "use_min_x")
274         sub = col.column()
275         sub.active = con.use_min_x
276         sub.prop(con, "min_x", text="")
277         col.prop(con, "use_max_x")
278         sub = col.column()
279         sub.active = con.use_max_x
280         sub.prop(con, "max_x", text="")
281
282         col = split.column()
283         col.prop(con, "use_min_y")
284         sub = col.column()
285         sub.active = con.use_min_y
286         sub.prop(con, "min_y", text="")
287         col.prop(con, "use_max_y")
288         sub = col.column()
289         sub.active = con.use_max_y
290         sub.prop(con, "max_y", text="")
291
292         col = split.column()
293         col.prop(con, "use_min_z")
294         sub = col.column()
295         sub.active = con.use_min_z
296         sub.prop(con, "min_z", text="")
297         col.prop(con, "use_max_z")
298         sub = col.column()
299         sub.active = con.use_max_z
300         sub.prop(con, "max_z", text="")
301
302         row = layout.row()
303         row.prop(con, "use_transform_limit")
304         row.label()
305
306         row = layout.row()
307         row.label(text="Convert:")
308         row.prop(con, "owner_space", text="")
309
310     def LIMIT_SCALE(self, context, layout, con):
311         split = layout.split()
312
313         col = split.column()
314         col.prop(con, "use_min_x")
315         sub = col.column()
316         sub.active = con.use_min_x
317         sub.prop(con, "min_x", text="")
318         col.prop(con, "use_max_x")
319         sub = col.column()
320         sub.active = con.use_max_x
321         sub.prop(con, "max_x", text="")
322
323         col = split.column()
324         col.prop(con, "use_min_y")
325         sub = col.column()
326         sub.active = con.use_min_y
327         sub.prop(con, "min_y", text="")
328         col.prop(con, "use_max_y")
329         sub = col.column()
330         sub.active = con.use_max_y
331         sub.prop(con, "max_y", text="")
332
333         col = split.column()
334         col.prop(con, "use_min_z")
335         sub = col.column()
336         sub.active = con.use_min_z
337         sub.prop(con, "min_z", text="")
338         col.prop(con, "use_max_z")
339         sub = col.column()
340         sub.active = con.use_max_z
341         sub.prop(con, "max_z", text="")
342
343         row = layout.row()
344         row.prop(con, "use_transform_limit")
345         row.label()
346
347         row = layout.row()
348         row.label(text="Convert:")
349         row.prop(con, "owner_space", text="")
350
351     def COPY_ROTATION(self, context, layout, con):
352         self.target_template(layout, con)
353
354         split = layout.split()
355
356         col = split.column()
357         col.prop(con, "use_x", text="X")
358         sub = col.column()
359         sub.active = con.use_x
360         sub.prop(con, "invert_x", text="Invert")
361
362         col = split.column()
363         col.prop(con, "use_y", text="Y")
364         sub = col.column()
365         sub.active = con.use_y
366         sub.prop(con, "invert_y", text="Invert")
367
368         col = split.column()
369         col.prop(con, "use_z", text="Z")
370         sub = col.column()
371         sub.active = con.use_z
372         sub.prop(con, "invert_z", text="Invert")
373
374         layout.prop(con, "use_offset")
375
376         self.space_template(layout, con)
377
378     def COPY_LOCATION(self, context, layout, con):
379         self.target_template(layout, con)
380
381         split = layout.split()
382
383         col = split.column()
384         col.prop(con, "use_x", text="X")
385         sub = col.column()
386         sub.active = con.use_x
387         sub.prop(con, "invert_x", text="Invert")
388
389         col = split.column()
390         col.prop(con, "use_y", text="Y")
391         sub = col.column()
392         sub.active = con.use_y
393         sub.prop(con, "invert_y", text="Invert")
394
395         col = split.column()
396         col.prop(con, "use_z", text="Z")
397         sub = col.column()
398         sub.active = con.use_z
399         sub.prop(con, "invert_z", text="Invert")
400
401         layout.prop(con, "use_offset")
402
403         self.space_template(layout, con)
404
405     def COPY_SCALE(self, context, layout, con):
406         self.target_template(layout, con)
407
408         row = layout.row(align=True)
409         row.prop(con, "use_x", text="X")
410         row.prop(con, "use_y", text="Y")
411         row.prop(con, "use_z", text="Z")
412
413         layout.prop(con, "use_offset")
414
415         self.space_template(layout, con)
416
417     def MAINTAIN_VOLUME(self, context, layout, con):
418
419         row = layout.row()
420         row.label(text="Free:")
421         row.prop(con, "free_axis", expand=True)
422
423         layout.prop(con, "volume")
424
425         self.space_template(layout, con)
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     def STRETCH_TO(self, context, layout, con):
480         self.target_template(layout, con)
481
482         row = layout.row()
483         row.prop(con, "rest_length", text="Rest Length")
484         row.operator("constraint.stretchto_reset", text="Reset")
485
486         layout.prop(con, "bulge", text="Volume Variation")
487
488         row = layout.row()
489         row.label(text="Volume:")
490         row.prop(con, "volume", expand=True)
491
492         row.label(text="Plane:")
493         row.prop(con, "keep_axis", expand=True)
494
495     def FLOOR(self, context, layout, con):
496         self.target_template(layout, con)
497
498         row = layout.row()
499         row.prop(con, "use_sticky")
500         row.prop(con, "use_rotation")
501
502         layout.prop(con, "offset")
503
504         row = layout.row()
505         row.label(text="Min/Max:")
506         row.prop(con, "floor_location", expand=True)
507
508         self.space_template(layout, con)
509
510     def RIGID_BODY_JOINT(self, context, layout, con):
511         self.target_template(layout, con, subtargets=False)
512
513         layout.prop(con, "pivot_type")
514         layout.prop(con, "child")
515
516         row = layout.row()
517         row.prop(con, "use_linked_collision", text="Linked Collision")
518         row.prop(con, "show_pivot", text="Display Pivot")
519
520         split = layout.split()
521
522         col = split.column(align=True)
523         col.label(text="Pivot:")
524         col.prop(con, "pivot_x", text="X")
525         col.prop(con, "pivot_y", text="Y")
526         col.prop(con, "pivot_z", text="Z")
527
528         col = split.column(align=True)
529         col.label(text="Axis:")
530         col.prop(con, "axis_x", text="X")
531         col.prop(con, "axis_y", text="Y")
532         col.prop(con, "axis_z", text="Z")
533
534         if con.pivot_type == 'CONE_TWIST':
535             layout.label(text="Limits:")
536             split = layout.split()
537
538             col = split.column()
539             col.prop(con, "use_angular_limit_x", text="Angle X")
540             sub = col.column()
541             sub.active = con.use_angular_limit_x
542             sub.prop(con, "limit_angle_max_x", text="")
543
544             col = split.column()
545             col.prop(con, "use_angular_limit_y", text="Angle Y")
546             sub = col.column()
547             sub.active = con.use_angular_limit_y
548             sub.prop(con, "limit_angle_max_y", text="")
549
550             col = split.column()
551             col.prop(con, "use_angular_limit_z", text="Angle Z")
552             sub = col.column()
553             sub.active = con.use_angular_limit_z
554             sub.prop(con, "limit_angle_max_z", text="")
555
556         elif con.pivot_type == 'GENERIC_6_DOF':
557             layout.label(text="Limits:")
558             split = layout.split()
559
560             col = split.column(align=True)
561             col.prop(con, "use_limit_x", text="X")
562             sub = col.column()
563             sub.active = con.use_limit_x
564             sub.prop(con, "limit_min_x", text="Min")
565             sub.prop(con, "limit_max_x", text="Max")
566
567             col = split.column(align=True)
568             col.prop(con, "use_limit_y", text="Y")
569             sub = col.column()
570             sub.active = con.use_limit_y
571             sub.prop(con, "limit_min_y", text="Min")
572             sub.prop(con, "limit_max_y", text="Max")
573
574             col = split.column(align=True)
575             col.prop(con, "use_limit_z", text="Z")
576             sub = col.column()
577             sub.active = con.use_limit_z
578             sub.prop(con, "limit_min_z", text="Min")
579             sub.prop(con, "limit_max_z", text="Max")
580
581             split = layout.split()
582
583             col = split.column(align=True)
584             col.prop(con, "use_angular_limit_x", text="Angle X")
585             sub = col.column()
586             sub.active = con.use_angular_limit_x
587             sub.prop(con, "limit_angle_min_x", text="Min")
588             sub.prop(con, "limit_angle_max_x", text="Max")
589
590             col = split.column(align=True)
591             col.prop(con, "use_angular_limit_y", text="Angle Y")
592             sub = col.column()
593             sub.active = con.use_angular_limit_y
594             sub.prop(con, "limit_angle_min_y", text="Min")
595             sub.prop(con, "limit_angle_max_y", text="Max")
596
597             col = split.column(align=True)
598             col.prop(con, "use_angular_limit_z", text="Angle Z")
599             sub = col.column()
600             sub.active = con.use_angular_limit_z
601             sub.prop(con, "limit_angle_min_z", text="Min")
602             sub.prop(con, "limit_angle_max_z", text="Max")
603
604         elif con.pivot_type == 'HINGE':
605             layout.label(text="Limits:")
606             split = layout.split()
607
608             row = split.row(align=True)
609             col = row.column()
610             col.prop(con, "use_angular_limit_x", text="Angle X")
611
612             col = row.column()
613             col.active = con.use_angular_limit_x
614             col.prop(con, "limit_angle_min_x", text="Min")
615             col = row.column()
616             col.active = con.use_angular_limit_x
617             col.prop(con, "limit_angle_max_x", text="Max")
618
619     def CLAMP_TO(self, context, layout, con):
620         self.target_template(layout, con)
621
622         row = layout.row()
623         row.label(text="Main Axis:")
624         row.prop(con, "main_axis", expand=True)
625
626         layout.prop(con, "use_cyclic")
627
628     def TRANSFORM(self, context, layout, con):
629         self.target_template(layout, con)
630
631         layout.prop(con, "use_motion_extrapolate", text="Extrapolate")
632
633         col = layout.column()
634         col.row().label(text="Source:")
635         col.row().prop(con, "map_from", expand=True)
636
637         split = layout.split()
638
639         sub = split.column(align=True)
640         sub.label(text="X:")
641         sub.prop(con, "from_min_x", text="Min")
642         sub.prop(con, "from_max_x", text="Max")
643
644         sub = split.column(align=True)
645         sub.label(text="Y:")
646         sub.prop(con, "from_min_y", text="Min")
647         sub.prop(con, "from_max_y", text="Max")
648
649         sub = split.column(align=True)
650         sub.label(text="Z:")
651         sub.prop(con, "from_min_z", text="Min")
652         sub.prop(con, "from_max_z", text="Max")
653
654         col = layout.column()
655         row = col.row()
656         row.label(text="Source to Destination Mapping:")
657
658         # note: chr(187) is the ASCII arrow ( >> ). Blender Text Editor can't
659         # open it. Thus we are using the hardcoded value instead.
660         row = col.row()
661         row.prop(con, "map_to_x_from", expand=False, text="")
662         row.label(text=" %s    X" % chr(187))
663
664         row = col.row()
665         row.prop(con, "map_to_y_from", expand=False, text="")
666         row.label(text=" %s    Y" % chr(187))
667
668         row = col.row()
669         row.prop(con, "map_to_z_from", expand=False, text="")
670         row.label(text=" %s    Z" % chr(187))
671
672         split = layout.split()
673
674         col = split.column()
675         col.label(text="Destination:")
676         col.row().prop(con, "map_to", expand=True)
677
678         split = layout.split()
679
680         col = split.column()
681         col.label(text="X:")
682
683         sub = col.column(align=True)
684         sub.prop(con, "to_min_x", text="Min")
685         sub.prop(con, "to_max_x", text="Max")
686
687         col = split.column()
688         col.label(text="Y:")
689
690         sub = col.column(align=True)
691         sub.prop(con, "to_min_y", text="Min")
692         sub.prop(con, "to_max_y", text="Max")
693
694         col = split.column()
695         col.label(text="Z:")
696
697         sub = col.column(align=True)
698         sub.prop(con, "to_min_z", text="Min")
699         sub.prop(con, "to_max_z", text="Max")
700
701         self.space_template(layout, con)
702
703     def SHRINKWRAP(self, context, layout, con):
704         self.target_template(layout, con, False)
705
706         layout.prop(con, "distance")
707         layout.prop(con, "shrinkwrap_type")
708
709         if con.shrinkwrap_type == 'PROJECT':
710             row = layout.row(align=True)
711             row.prop(con, "use_x")
712             row.prop(con, "use_y")
713             row.prop(con, "use_z")
714
715     def DAMPED_TRACK(self, context, layout, con):
716         self.target_template(layout, con)
717
718         row = layout.row()
719         row.label(text="To:")
720         row.prop(con, "track_axis", expand=True)
721
722     def SPLINE_IK(self, context, layout, con):
723         self.target_template(layout, con)
724
725         col = layout.column()
726         col.label(text="Spline Fitting:")
727         col.prop(con, "chain_count")
728         col.prop(con, "use_even_divisions")
729         col.prop(con, "use_chain_offset")
730
731         col = layout.column()
732         col.label(text="Chain Scaling:")
733         col.prop(con, "use_y_stretch")
734         col.prop(con, "xz_scale_mode")
735         col.prop(con, "use_curve_radius")
736
737     def PIVOT(self, context, layout, con):
738         self.target_template(layout, con)
739
740         if con.target:
741             col = layout.column()
742             col.prop(con, "offset", text="Pivot Offset")
743         else:
744             col = layout.column()
745             col.prop(con, "use_relative_location")
746             if con.use_relative_location:
747                 col.prop(con, "offset", text="Relative Pivot Point")
748             else:
749                 col.prop(con, "offset", text="Absolute Pivot Point")
750
751         col = layout.column()
752         col.prop(con, "rotation_range", text="Pivot When")
753
754     def SCRIPT(self, context, layout, con):
755         layout.label("Blender 2.5 has no py-constraints")
756
757
758 class OBJECT_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
759     bl_label = "Object Constraints"
760     bl_context = "constraint"
761
762     @classmethod
763     def poll(cls, context):
764         return (context.object)
765
766     def draw(self, context):
767         layout = self.layout
768
769         ob = context.object
770
771         if ob.mode == 'POSE':
772             box = layout.box()
773             box.alert = True
774             box.label(icon='INFO', text="See Bone Constraints tab to Add Constraints to active bone")
775         else:
776             layout.operator_menu_enum("object.constraint_add", "type")
777
778         for con in ob.constraints:
779             self.draw_constraint(context, con)
780
781
782 class BONE_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
783     bl_label = "Bone Constraints"
784     bl_context = "bone_constraint"
785
786     @classmethod
787     def poll(cls, context):
788         return (context.pose_bone)
789
790     def draw(self, context):
791         layout = self.layout
792
793         layout.operator_menu_enum("pose.constraint_add", "type")
794
795         for con in context.pose_bone.constraints:
796             self.draw_constraint(context, con)
797
798 if __name__ == "__main__":  # only for live edit.
799     bpy.utils.register_module(__name__)