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