change blender python interface for classes not to ise __idname__ rather bl_idname...
[blender-staging.git] / release / scripts / ui / buttons_object_constraint.py
1
2 import bpy
3
4 class ConstraintButtonsPanel(bpy.types.Panel):
5         bl_space_type = 'PROPERTIES'
6         bl_region_type = 'WINDOW'
7         bl_context = "constraint"
8
9         def draw_constraint(self, context, con):
10                 layout = self.layout
11                 
12                 box = layout.template_constraint(con)
13
14                 if box:
15                         # match enum type to our functions, avoids a lookup table.
16                         getattr(self, con.type)(context, box, con)
17         
18                         # show/key buttons here are most likely obsolete now, with
19                         # keyframing functionality being part of every button
20                         if con.type not in ('RIGID_BODY_JOINT', 'NULL'):
21                                 box.itemR(con, "influence")
22         
23         def space_template(self, layout, con, target=True, owner=True):
24                 if target or owner:
25                         row = layout.row()
26
27                         row.itemL(text="Convert:")
28
29                         if target:
30                                 row.itemR(con, "target_space", text="")
31
32                         if target and owner:
33                                 row.itemL(icon='ICON_ARROW_LEFTRIGHT')
34
35                         if owner:
36                                 row.itemR(con, "owner_space", text="")
37                         
38         def target_template(self, layout, con, subtargets=True):
39                 layout.itemR(con, "target") # XXX limiting settings for only 'curves' or some type of object
40                 
41                 if con.target and subtargets:
42                         if con.target.type == 'ARMATURE':
43                                 layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone")
44                                 
45                                 if con.type == 'COPY_LOCATION':
46                                         row = layout.row()
47                                         row.itemL(text="Head/Tail:")
48                                         row.itemR(con, "head_tail", text="")
49                         elif con.target.type in ('MESH', 'LATTICE'):
50                                 layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
51
52         def ik_template(self, layout, con):
53                 # only used for iTaSC
54                 layout.itemR(con, "pole_target")
55         
56                 if con.pole_target and con.pole_target.type == 'ARMATURE':
57                         layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
58                 
59                 if con.pole_target:
60                         row = layout.row()
61                         row.itemL()
62                         row.itemR(con, "pole_angle")
63                 
64                 split = layout.split(percentage=0.33)
65                 col = split.column()
66                 col.itemR(con, "tail")
67                 col.itemR(con, "stretch")
68
69                 col = split.column()
70                 col.itemR(con, "chain_length")
71                 col.itemR(con, "targetless")
72
73         def CHILD_OF(self, context, layout, con):
74                 self.target_template(layout, con)
75
76                 split = layout.split()
77                 
78                 col = split.column()
79                 col.itemL(text="Location:")
80                 col.itemR(con, "locationx", text="X")
81                 col.itemR(con, "locationy", text="Y")
82                 col.itemR(con, "locationz", text="Z")
83                 
84                 col = split.column()
85                 col.itemL(text="Rotation:")
86                 col.itemR(con, "rotationx", text="X")
87                 col.itemR(con, "rotationy", text="Y")
88                 col.itemR(con, "rotationz", text="Z")
89                 
90                 col = split.column()
91                 col.itemL(text="Scale:")
92                 col.itemR(con, "sizex", text="X")
93                 col.itemR(con, "sizey", text="Y")
94                 col.itemR(con, "sizez", text="Z")
95                 
96                 row = layout.row()
97                 row.itemO("constraint.childof_set_inverse")
98                 row.itemO("constraint.childof_clear_inverse")
99                 
100         def TRACK_TO(self, context, layout, con):
101                 self.target_template(layout, con)
102                 
103                 row = layout.row()
104                 row.itemL(text="To:")
105                 row.itemR(con, "track", expand=True)
106                 
107                 row = layout.row()
108                 #row.itemR(con, "up", text="Up", expand=True) # XXX: up and expand don't play nice together
109                 row.itemR(con, "up", text="Up")
110                 row.itemR(con, "target_z")
111                 
112                 self.space_template(layout, con)
113                 
114         def IK(self, context, layout, con):
115                 if context.object.pose.ik_solver == "ITASC":
116                         layout.itemR(con, "ik_type")
117                         getattr(self, "IK_"+con.ik_type)(context, layout, con)
118                 else:
119                         # Legacy IK constraint
120                         self.target_template(layout, con)
121                         layout.itemR(con, "pole_target")
122         
123                         if con.pole_target and con.pole_target.type == 'ARMATURE':
124                                 layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
125                 
126                         if con.pole_target:
127                                 row = layout.row()
128                                 row.itemL()
129                                 row.itemR(con, "pole_angle")
130                 
131                         split = layout.split()
132                         col = split.column()
133                         col.itemR(con, "tail")
134                         col.itemR(con, "stretch")
135
136                         col = split.column()
137                         col.itemR(con, "iterations")
138                         col.itemR(con, "chain_length")
139                         
140                         split = layout.split()
141                         col = split.column()
142                         col.itemL()
143                         col.itemR(con, "targetless")
144                         col.itemR(con, "rotation")
145
146                         col = split.column()
147                         col.itemL(text="Weight:")
148                         col.itemR(con, "weight", text="Position", slider=True)
149                         sub = col.column()
150                         sub.active = con.rotation
151                         sub.itemR(con, "orient_weight", text="Rotation", slider=True)
152
153         def IK_COPY_POSE(self, context, layout, con):
154                 self.target_template(layout, con)
155                 self.ik_template(layout, con)
156         
157                 row = layout.row()
158                 row.itemL(text="Axis Ref:")
159                 row.itemR(con, "axis_reference", expand=True)
160                 split = layout.split(percentage=0.33)
161                 split.row().itemR(con, "position")
162                 row = split.row()
163                 row.itemR(con, "weight", text="Weight", slider=True)
164                 row.active = con.position
165                 split = layout.split(percentage=0.33)
166                 row = split.row()
167                 row.itemL(text="Lock:")
168                 row = split.row()
169                 row.itemR(con, "pos_lock_x", text="X")
170                 row.itemR(con, "pos_lock_y", text="Y")
171                 row.itemR(con, "pos_lock_z", text="Z")
172                 split.active = con.position
173                 
174                 split = layout.split(percentage=0.33)
175                 split.row().itemR(con, "rotation")
176                 row = split.row()
177                 row.itemR(con, "orient_weight", text="Weight", slider=True)
178                 row.active = con.rotation
179                 split = layout.split(percentage=0.33)
180                 row = split.row()
181                 row.itemL(text="Lock:")
182                 row = split.row()
183                 row.itemR(con, "rot_lock_x", text="X")
184                 row.itemR(con, "rot_lock_y", text="Y")
185                 row.itemR(con, "rot_lock_z", text="Z")
186                 split.active = con.rotation
187                 
188         def IK_DISTANCE(self, context, layout, con):
189                 self.target_template(layout, con)
190                 self.ik_template(layout, con)
191
192                 layout.itemR(con, "limit_mode")
193                 row = layout.row()
194                 row.itemR(con, "weight", text="Weight", slider=True)
195                 row.itemR(con, "distance", text="Distance", slider=True)
196
197         def FOLLOW_PATH(self, context, layout, con):
198                 self.target_template(layout, con)
199                 
200                 split = layout.split()
201                 
202                 col = split.column()
203                 col.itemR(con, "use_curve_follow")
204                 col.itemR(con, "use_curve_radius")
205                 
206                 col = split.column()
207                 col.itemR(con, "use_fixed_position")
208                 if con.use_fixed_position:
209                         col.itemR(con, "offset_factor", text="Offset")
210                 else:
211                         col.itemR(con, "offset")
212                 
213                 row = layout.row()
214                 row.itemL(text="Forward:")
215                 row.itemR(con, "forward", expand=True)
216                 
217                 row = layout.row()
218                 row.itemR(con, "up", text="Up")
219                 row.itemL()
220                 
221         def LIMIT_ROTATION(self, context, layout, con):
222                 
223                 split = layout.split()
224                 
225                 col = split.column()
226                 col.itemR(con, "use_limit_x")
227                 sub = col.column()
228                 sub.active = con.use_limit_x
229                 sub.itemR(con, "minimum_x", text="Min")
230                 sub.itemR(con, "maximum_x", text="Max")
231                 
232                 col = split.column()
233                 col.itemR(con, "use_limit_y")
234                 sub = col.column()
235                 sub.active = con.use_limit_y
236                 sub.itemR(con, "minimum_y", text="Min")
237                 sub.itemR(con, "maximum_y", text="Max")
238                 
239                 col = split.column()
240                 col.itemR(con, "use_limit_z")
241                 sub = col.column()
242                 sub.active = con.use_limit_z
243                 sub.itemR(con, "minimum_z", text="Min")
244                 sub.itemR(con, "maximum_z", text="Max")
245                 
246                 row = layout.row()
247                 row.itemR(con, "limit_transform")
248                 row.itemL()
249                 
250                 row = layout.row()
251                 row.itemL(text="Convert:")
252                 row.itemR(con, "owner_space", text="")
253                 
254         def LIMIT_LOCATION(self, context, layout, con):
255                 split = layout.split()
256                 
257                 col = split.column()
258                 col.itemR(con, "use_minimum_x")
259                 sub = col.column()
260                 sub.active = con.use_minimum_x
261                 sub.itemR(con, "minimum_x", text="")
262                 col.itemR(con, "use_maximum_x")
263                 sub = col.column()
264                 sub.active = con.use_maximum_x
265                 sub.itemR(con, "maximum_x", text="")
266                 
267                 col = split.column()
268                 col.itemR(con, "use_minimum_y")
269                 sub = col.column()
270                 sub.active = con.use_minimum_y
271                 sub.itemR(con, "minimum_y", text="")
272                 col.itemR(con, "use_maximum_y")
273                 sub = col.column()
274                 sub.active = con.use_maximum_y
275                 sub.itemR(con, "maximum_y", text="")
276                 
277                 col = split.column()
278                 col.itemR(con, "use_minimum_z")
279                 sub = col.column()
280                 sub.active = con.use_minimum_z
281                 sub.itemR(con, "minimum_z", text="")
282                 col.itemR(con, "use_maximum_z")
283                 sub = col.column()
284                 sub.active = con.use_maximum_z
285                 sub.itemR(con, "maximum_z", text="")
286         
287                 row = layout.row()
288                 row.itemR(con, "limit_transform")
289                 row.itemL()
290                 
291                 row = layout.row()
292                 row.itemL(text="Convert:")
293                 row.itemR(con, "owner_space", text="")
294                 
295         def LIMIT_SCALE(self, context, layout, con):
296                 split = layout.split()
297
298                 col = split.column()
299                 col.itemR(con, "use_minimum_x")
300                 sub = col.column()
301                 sub.active = con.use_minimum_x
302                 sub.itemR(con, "minimum_x", text="")
303                 col.itemR(con, "use_maximum_x")
304                 sub = col.column()
305                 sub.active = con.use_maximum_x
306                 sub.itemR(con, "maximum_x", text="")
307                 
308                 col = split.column()
309                 col.itemR(con, "use_minimum_y")
310                 sub = col.column()
311                 sub.active = con.use_minimum_y
312                 sub.itemR(con, "minimum_y", text="")
313                 col.itemR(con, "use_maximum_y")
314                 sub = col.column()
315                 sub.active = con.use_maximum_y
316                 sub.itemR(con, "maximum_y", text="")
317                 
318                 col = split.column()
319                 col.itemR(con, "use_minimum_z")
320                 sub = col.column()
321                 sub.active = con.use_minimum_z
322                 sub.itemR(con, "minimum_z", text="")
323                 col.itemR(con, "use_maximum_z")
324                 sub = col.column()
325                 sub.active = con.use_maximum_z
326                 sub.itemR(con, "maximum_z", text="")
327                 
328                 row = layout.row()
329                 row.itemR(con, "limit_transform")
330                 row.itemL()
331                 
332                 row = layout.row()
333                 row.itemL(text="Convert:")
334                 row.itemR(con, "owner_space", text="")
335         
336         def COPY_ROTATION(self, context, layout, con):
337                 self.target_template(layout, con)
338                 
339                 split = layout.split()
340                 
341                 col = split.column()
342                 col.itemR(con, "rotate_like_x", text="X")
343                 sub = col.column()
344                 sub.active = con.rotate_like_x
345                 sub.itemR(con, "invert_x", text="Invert")
346                 
347                 col = split.column()
348                 col.itemR(con, "rotate_like_y", text="Y")
349                 sub = col.column()
350                 sub.active = con.rotate_like_y
351                 sub.itemR(con, "invert_y", text="Invert")
352                 
353                 col = split.column()
354                 col.itemR(con, "rotate_like_z", text="Z")
355                 sub = col.column()
356                 sub.active = con.rotate_like_z
357                 sub.itemR(con, "invert_z", text="Invert")
358
359                 layout.itemR(con, "offset")
360                 
361                 self.space_template(layout, con)
362                 
363         def COPY_LOCATION(self, context, layout, con):
364                 self.target_template(layout, con)
365                 
366                 split = layout.split()
367                 
368                 col = split.column()
369                 col.itemR(con, "locate_like_x", text="X")
370                 sub = col.column()
371                 sub.active = con.locate_like_x
372                 sub.itemR(con, "invert_x", text="Invert")
373                 
374                 col = split.column()
375                 col.itemR(con, "locate_like_y", text="Y")
376                 sub = col.column()
377                 sub.active = con.locate_like_y
378                 sub.itemR(con, "invert_y", text="Invert")
379                 
380                 col = split.column()
381                 col.itemR(con, "locate_like_z", text="Z")
382                 sub = col.column()
383                 sub.active = con.locate_like_z
384                 sub.itemR(con, "invert_z", text="Invert")
385
386                 layout.itemR(con, "offset")
387                         
388                 self.space_template(layout, con)
389                 
390         def COPY_SCALE(self, context, layout, con):
391                 self.target_template(layout, con)
392                 
393                 row = layout.row(align=True)
394                 row.itemR(con, "size_like_x", text="X")
395                 row.itemR(con, "size_like_y", text="Y")
396                 row.itemR(con, "size_like_z", text="Z")
397
398                 layout.itemR(con, "offset")
399                 
400                 self.space_template(layout, con)
401                 
402         #def SCRIPT(self, context, layout, con):
403         
404         def ACTION(self, context, layout, con):
405                 self.target_template(layout, con)
406                 
407                 layout.itemR(con, "action")
408                 layout.itemR(con, "transform_channel")
409
410                 split = layout.split()
411         
412                 col = split.column(align=True)
413                 col.itemR(con, "start_frame", text="Start")
414                 col.itemR(con, "end_frame", text="End")
415                 
416                 col = split.column(align=True)
417                 col.itemR(con, "minimum", text="Min")
418                 col.itemR(con, "maximum", text="Max")
419                 
420                 row = layout.row()
421                 row.itemL(text="Convert:")
422                 row.itemR(con, "owner_space", text="")
423         
424         def LOCKED_TRACK(self, context, layout, con):
425                 self.target_template(layout, con)
426                 
427                 row = layout.row()
428                 row.itemL(text="To:")
429                 row.itemR(con, "track", expand=True)
430                 
431                 row = layout.row()
432                 row.itemL(text="Lock:")
433                 row.itemR(con, "locked", expand=True)
434                 
435         def LIMIT_DISTANCE(self, context, layout, con):
436                 self.target_template(layout, con)
437                 
438                 col = layout.column(align=True);
439                 col.itemR(con, "distance")
440                 col.itemO("constraint.limitdistance_reset")
441                 
442                 row = layout.row()
443                 row.itemL(text="Clamp Region:")
444                 row.itemR(con, "limit_mode", text="")
445                 
446         def STRETCH_TO(self, context, layout, con):
447                 self.target_template(layout, con)
448                 
449                 row = layout.row()
450                 row.itemR(con, "original_length", text="Rest Length")
451                 row.itemO("constraint.stretchto_reset", text="Reset")
452                 
453                 col = layout.column()
454                 col.itemR(con, "bulge", text="Volume Variation")
455                 
456                 row = layout.row()
457                 row.itemL(text="Volume:")
458                 row.itemR(con, "volume", expand=True)
459                 row.itemL(text="Plane:")
460                 row.itemR(con, "keep_axis", expand=True)
461                 
462         def FLOOR(self, context, layout, con):
463                 self.target_template(layout, con)
464                 
465                 row = layout.row()
466                 row.itemR(con, "sticky")
467                 row.itemR(con, "use_rotation")
468                 
469                 layout.itemR(con, "offset")
470                 
471                 row = layout.row()
472                 row.itemL(text="Min/Max:")
473                 row.itemR(con, "floor_location", expand=True)
474                 
475         def RIGID_BODY_JOINT(self, context, layout, con):
476                 self.target_template(layout, con)
477                 
478                 layout.itemR(con, "pivot_type")
479                 layout.itemR(con, "child")
480                 
481                 row = layout.row()
482                 row.itemR(con, "disable_linked_collision", text="No Collision")
483                 row.itemR(con, "draw_pivot", text="Display Pivot")
484                 
485                 split = layout.split()
486                 
487                 col = split.column(align=True)
488                 col.itemL(text="Pivot:")
489                 col.itemR(con, "pivot_x", text="X")
490                 col.itemR(con, "pivot_y", text="Y")
491                 col.itemR(con, "pivot_z", text="Z")
492                 
493                 col = split.column(align=True)
494                 col.itemL(text="Axis:")
495                 col.itemR(con, "axis_x", text="X")
496                 col.itemR(con, "axis_y", text="Y")
497                 col.itemR(con, "axis_z", text="Z")
498                 
499                 #Missing: Limit arrays (not wrapped in RNA yet) 
500         
501         def CLAMP_TO(self, context, layout, con):
502                 self.target_template(layout, con)
503                 
504                 row = layout.row()
505                 row.itemL(text="Main Axis:")
506                 row.itemR(con, "main_axis", expand=True)
507                 
508                 row = layout.row()
509                 row.itemR(con, "cyclic")
510                 
511         def TRANSFORM(self, context, layout, con):
512                 self.target_template(layout, con)
513                 
514                 layout.itemR(con, "extrapolate_motion", text="Extrapolate")
515                 
516                 split = layout.split()
517                 
518                 col = split.column()
519                 col.itemL(text="Source:")
520                 col.row().itemR(con, "map_from", expand=True)
521                 
522                 sub = col.row(align=True)
523                 sub.itemL(text="X:")
524                 sub.itemR(con, "from_min_x", text="")
525                 sub.itemR(con, "from_max_x", text="")
526                 
527                 sub = col.row(align=True)
528                 sub.itemL(text="Y:")
529                 sub.itemR(con, "from_min_y", text="")
530                 sub.itemR(con, "from_max_y", text="")
531                 
532                 sub = col.row(align=True)
533                 sub.itemL(text="Z:")
534                 sub.itemR(con, "from_min_z", text="")
535                 sub.itemR(con, "from_max_z", text="")
536                 
537                 split = layout.split()
538                 
539                 col = split.column()
540                 col.itemL(text="Destination:")
541                 col.row().itemR(con, "map_to", expand=True)
542
543                 sub = col.row(align=True)
544                 sub.itemR(con, "map_to_x_from", text="")
545                 sub.itemR(con, "to_min_x", text="")
546                 sub.itemR(con, "to_max_x", text="")
547                 
548                 sub = col.row(align=True)
549                 sub.itemR(con, "map_to_y_from", text="")
550                 sub.itemR(con, "to_min_y", text="")
551                 sub.itemR(con, "to_max_y", text="")
552                 
553                 sub = col.row(align=True)
554                 sub.itemR(con, "map_to_z_from", text="")
555                 sub.itemR(con, "to_min_z", text="")
556                 sub.itemR(con, "to_max_z", text="")
557                 
558                 self.space_template(layout, con)
559                 
560         def SHRINKWRAP (self, context, layout, con):
561                 self.target_template(layout, con)
562                 
563                 layout.itemR(con, "distance")
564                 layout.itemR(con, "shrinkwrap_type")
565                 
566                 if con.shrinkwrap_type == 'PROJECT':
567                         row = layout.row(align=True)
568                         row.itemR(con, "axis_x")
569                         row.itemR(con, "axis_y")
570                         row.itemR(con, "axis_z")
571                         
572         def DAMPED_TRACK(self, context, layout, con):
573                 self.target_template(layout, con)
574                 
575                 row = layout.row()
576                 row.itemL(text="To:")
577                 row.itemR(con, "track", expand=True)
578                 
579 class OBJECT_PT_constraints(ConstraintButtonsPanel):
580         bl_label = "Constraints"
581         bl_context = "constraint"
582
583         def poll(self, context):
584                 return (context.object)
585                 
586         def draw(self, context):
587                 layout = self.layout
588                 ob = context.object
589
590                 row = layout.row()
591                 row.item_menu_enumO("object.constraint_add", "type")
592                 row.itemL();
593
594                 for con in ob.constraints:
595                         self.draw_constraint(context, con)
596
597 class BONE_PT_inverse_kinematics(ConstraintButtonsPanel):
598         bl_label = "Inverse Kinematics"
599         bl_default_closed = True
600         bl_context = "bone_constraint"
601         
602         def poll(self, context):
603                 ob = context.object
604                 bone = context.bone
605
606                 if ob and bone:
607                         pchan = ob.pose.pose_channels[bone.name]
608                         return pchan.has_ik
609                 
610                 return False
611
612         def draw(self, context):
613                 layout = self.layout
614                 
615                 ob = context.object
616                 bone = context.bone
617                 pchan = ob.pose.pose_channels[bone.name]
618
619                 row = layout.row()
620                 row.itemR(ob.pose, "ik_solver")
621
622                 split = layout.split(percentage=0.25)
623                 split.itemR(pchan, "ik_dof_x", text="X")
624                 row = split.row()
625                 row.itemR(pchan, "ik_stiffness_x", text="Stiffness", slider=True)
626                 row.active = pchan.ik_dof_x
627
628                 split = layout.split(percentage=0.25)
629                 row = split.row()
630                 row.itemR(pchan, "ik_limit_x", text="Limit")
631                 row.active = pchan.ik_dof_x
632                 row = split.row(align=True)
633                 row.itemR(pchan, "ik_min_x", text="")
634                 row.itemR(pchan, "ik_max_x", text="")
635                 row.active = pchan.ik_dof_x and pchan.ik_limit_x
636
637                 split = layout.split(percentage=0.25)
638                 split.itemR(pchan, "ik_dof_y", text="Y")
639                 row = split.row()
640                 row.itemR(pchan, "ik_stiffness_y", text="Stiffness", slider=True)
641                 row.active = pchan.ik_dof_y
642
643                 split = layout.split(percentage=0.25)
644                 row = split.row()
645                 row.itemR(pchan, "ik_limit_y", text="Limit")
646                 row.active = pchan.ik_dof_y
647                 row = split.row(align=True)
648                 row.itemR(pchan, "ik_min_y", text="")
649                 row.itemR(pchan, "ik_max_y", text="")
650                 row.active = pchan.ik_dof_y and pchan.ik_limit_y
651
652                 split = layout.split(percentage=0.25)
653                 split.itemR(pchan, "ik_dof_z", text="Z")
654                 row = split.row()
655                 row.itemR(pchan, "ik_stiffness_z", text="Stiffness", slider=True)
656                 row.active = pchan.ik_dof_z
657
658                 split = layout.split(percentage=0.25)
659                 row = split.row()
660                 row.itemR(pchan, "ik_limit_z", text="Limit")
661                 row.active = pchan.ik_dof_z
662                 row = split.row(align=True)
663                 row.itemR(pchan, "ik_min_z", text="")
664                 row.itemR(pchan, "ik_max_z", text="")
665                 row.active = pchan.ik_dof_z and pchan.ik_limit_z
666                 split = layout.split()
667                 split.itemR(pchan, "ik_stretch", text="Stretch", slider=True)
668                 split.itemL()
669
670                 if ob.pose.ik_solver == "ITASC":
671                         row = layout.row()
672                         row.itemR(pchan, "ik_rot_control", text="Control Rotation")
673                         row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True)
674                         # not supported yet
675                         #row = layout.row()
676                         #row.itemR(pchan, "ik_lin_control", text="Joint Size")
677                         #row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True)
678
679 class BONE_PT_iksolver_itasc(ConstraintButtonsPanel):
680         bl_label = "iTaSC parameters"
681         bl_default_closed = True
682         bl_context = "bone_constraint"
683         
684         def poll(self, context):
685                 ob = context.object
686                 bone = context.bone
687
688                 if ob and bone:
689                         pchan = ob.pose.pose_channels[bone.name]
690                         return pchan.has_ik and ob.pose.ik_solver == "ITASC" and ob.pose.ik_param
691                 
692                 return False
693
694         def draw(self, context):
695                 layout = self.layout
696
697                 ob = context.object
698                 itasc = ob.pose.ik_param
699
700                 layout.itemR(itasc, "mode", expand=True)
701                 simulation = itasc.mode == "SIMULATION"
702                 if simulation:
703                         layout.itemL(text="Reiteration:")
704                         layout.itemR(itasc, "reiteration", expand=True)
705                 
706                 flow = layout.column_flow()
707                 flow.itemR(itasc, "precision", text="Prec")
708                 flow.itemR(itasc, "num_iter", text="Iter")
709                 flow.active = not simulation or itasc.reiteration != "NEVER"
710
711                 if simulation:          
712                         layout.itemR(itasc, "auto_step")
713                         row = layout.row()
714                         if itasc.auto_step:
715                                 row.itemR(itasc, "min_step", text="Min")
716                                 row.itemR(itasc, "max_step", text="Max")
717                         else:
718                                 row.itemR(itasc, "num_step")
719                         
720                 layout.itemR(itasc, "solver")
721                 if simulation:
722                         layout.itemR(itasc, "feedback")
723                         layout.itemR(itasc, "max_velocity")
724                 if itasc.solver == "DLS":
725                         row = layout.row()
726                         row.itemR(itasc, "dampmax", text="Damp", slider=True)
727                         row.itemR(itasc, "dampeps", text="Eps", slider=True)
728
729 class BONE_PT_constraints(ConstraintButtonsPanel):
730         bl_label = "Constraints"
731         bl_context = "bone_constraint"
732
733         def poll(self, context):
734                 ob = context.object
735                 return (ob and ob.type == 'ARMATURE' and context.bone)
736                 
737         def draw(self, context):
738                 layout = self.layout
739                 
740                 ob = context.object
741                 pchan = ob.pose.pose_channels[context.bone.name]
742
743                 row = layout.row()
744                 row.item_menu_enumO("pose.constraint_add", "type")
745                 row.itemL();
746
747                 for con in pchan.constraints:
748                         self.draw_constraint(context, con)
749
750 bpy.types.register(OBJECT_PT_constraints)
751 bpy.types.register(BONE_PT_iksolver_itasc)
752 bpy.types.register(BONE_PT_inverse_kinematics)
753 bpy.types.register(BONE_PT_constraints)