Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / release / ui / buttons_object_constraint.py
1
2 import bpy
3
4 class ConstraintButtonsPanel(bpy.types.Panel):
5         __space_type__ = 'PROPERTIES'
6         __region_type__ = 'WINDOW'
7         __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                 layout.itemR(con, "pole_target")
54         
55                 if con.pole_target and con.pole_target.type == 'ARMATURE':
56                         layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
57                 
58                 if con.pole_target:
59                         row = layout.row()
60                         row.itemL()
61                         row.itemR(con, "pole_angle")
62                 
63                 split = layout.split()
64                 col = split.column()
65                 col.itemR(con, "tail")
66                 col.itemR(con, "stretch")
67
68                 col = split.column()
69                 col.itemR(con, "iterations")
70                 col.itemR(con, "chain_length")
71                 
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                         self.IK_COPY_POSE(context, layout, con)
120
121         def IK_COPY_POSE(self, context, layout, con):
122                 self.target_template(layout, con)
123                 self.ik_template(layout, con)
124
125                 split = layout.split()
126                 col = split.column()
127                 col.itemL()
128                 col.itemR(con, "targetless")
129                 col.itemR(con, "rotation")
130
131                 col = split.column()
132                 col.itemL(text="Weight:")
133                 col.itemR(con, "weight", text="Position", slider=True)
134                 sub = col.column()
135                 sub.active = con.rotation
136                 sub.itemR(con, "orient_weight", text="Rotation", slider=True)
137                 
138         def IK_DISTANCE(self, context, layout, con):
139                 self.target_template(layout, con)
140                 self.ik_template(layout, con)
141
142                 layout.itemR(con, "limit_mode")
143                 row = layout.row()
144                 row.itemR(con, "weight", text="Weight", slider=True)
145                 row.itemR(con, "distance", text="Distance", slider=True)
146
147         def FOLLOW_PATH(self, context, layout, con):
148                 self.target_template(layout, con)
149                 
150                 split = layout.split()
151                 
152                 col = split.column()
153                 col.itemR(con, "use_curve_follow")
154                 col.itemR(con, "use_curve_radius")
155                 
156                 col = split.column()
157                 col.itemR(con, "use_fixed_position")
158                 if con.use_fixed_position:
159                         col.itemR(con, "offset_factor", text="Offset")
160                 else:
161                         col.itemR(con, "offset")
162                 
163                 row = layout.row()
164                 row.itemL(text="Forward:")
165                 row.itemR(con, "forward", expand=True)
166                 
167                 row = layout.row()
168                 row.itemR(con, "up", text="Up")
169                 row.itemL()
170                 
171         def LIMIT_ROTATION(self, context, layout, con):
172                 
173                 split = layout.split()
174                 
175                 col = split.column()
176                 col.itemR(con, "use_limit_x")
177                 sub = col.column()
178                 sub.active = con.use_limit_x
179                 sub.itemR(con, "minimum_x", text="Min")
180                 sub.itemR(con, "maximum_x", text="Max")
181                 
182                 col = split.column()
183                 col.itemR(con, "use_limit_y")
184                 sub = col.column()
185                 sub.active = con.use_limit_y
186                 sub.itemR(con, "minimum_y", text="Min")
187                 sub.itemR(con, "maximum_y", text="Max")
188                 
189                 col = split.column()
190                 col.itemR(con, "use_limit_z")
191                 sub = col.column()
192                 sub.active = con.use_limit_z
193                 sub.itemR(con, "minimum_z", text="Min")
194                 sub.itemR(con, "maximum_z", text="Max")
195                 
196                 row = layout.row()
197                 row.itemR(con, "limit_transform")
198                 row.itemL()
199                 
200                 row = layout.row()
201                 row.itemL(text="Convert:")
202                 row.itemR(con, "owner_space", text="")
203                 
204         def LIMIT_LOCATION(self, context, layout, con):
205                 split = layout.split()
206                 
207                 col = split.column()
208                 col.itemR(con, "use_minimum_x")
209                 sub = col.column()
210                 sub.active = con.use_minimum_x
211                 sub.itemR(con, "minimum_x", text="")
212                 col.itemR(con, "use_maximum_x")
213                 sub = col.column()
214                 sub.active = con.use_maximum_x
215                 sub.itemR(con, "maximum_x", text="")
216                 
217                 col = split.column()
218                 col.itemR(con, "use_minimum_y")
219                 sub = col.column()
220                 sub.active = con.use_minimum_y
221                 sub.itemR(con, "minimum_y", text="")
222                 col.itemR(con, "use_maximum_y")
223                 sub = col.column()
224                 sub.active = con.use_maximum_y
225                 sub.itemR(con, "maximum_y", text="")
226                 
227                 col = split.column()
228                 col.itemR(con, "use_minimum_z")
229                 sub = col.column()
230                 sub.active = con.use_minimum_z
231                 sub.itemR(con, "minimum_z", text="")
232                 col.itemR(con, "use_maximum_z")
233                 sub = col.column()
234                 sub.active = con.use_maximum_z
235                 sub.itemR(con, "maximum_z", text="")
236         
237                 row = layout.row()
238                 row.itemR(con, "limit_transform")
239                 row.itemL()
240                 
241                 row = layout.row()
242                 row.itemL(text="Convert:")
243                 row.itemR(con, "owner_space", text="")
244                 
245         def LIMIT_SCALE(self, context, layout, con):
246                 split = layout.split()
247
248                 col = split.column()
249                 col.itemR(con, "use_minimum_x")
250                 sub = col.column()
251                 sub.active = con.use_minimum_x
252                 sub.itemR(con, "minimum_x", text="")
253                 col.itemR(con, "use_maximum_x")
254                 sub = col.column()
255                 sub.active = con.use_maximum_x
256                 sub.itemR(con, "maximum_x", text="")
257                 
258                 col = split.column()
259                 col.itemR(con, "use_minimum_y")
260                 sub = col.column()
261                 sub.active = con.use_minimum_y
262                 sub.itemR(con, "minimum_y", text="")
263                 col.itemR(con, "use_maximum_y")
264                 sub = col.column()
265                 sub.active = con.use_maximum_y
266                 sub.itemR(con, "maximum_y", text="")
267                 
268                 col = split.column()
269                 col.itemR(con, "use_minimum_z")
270                 sub = col.column()
271                 sub.active = con.use_minimum_z
272                 sub.itemR(con, "minimum_z", text="")
273                 col.itemR(con, "use_maximum_z")
274                 sub = col.column()
275                 sub.active = con.use_maximum_z
276                 sub.itemR(con, "maximum_z", text="")
277                 
278                 row = layout.row()
279                 row.itemR(con, "limit_transform")
280                 row.itemL()
281                 
282                 row = layout.row()
283                 row.itemL(text="Convert:")
284                 row.itemR(con, "owner_space", text="")
285         
286         def COPY_ROTATION(self, context, layout, con):
287                 self.target_template(layout, con)
288                 
289                 split = layout.split()
290                 
291                 col = split.column()
292                 col.itemR(con, "rotate_like_x", text="X")
293                 sub = col.column()
294                 sub.active = con.rotate_like_x
295                 sub.itemR(con, "invert_x", text="Invert")
296                 
297                 col = split.column()
298                 col.itemR(con, "rotate_like_y", text="Y")
299                 sub = col.column()
300                 sub.active = con.rotate_like_y
301                 sub.itemR(con, "invert_y", text="Invert")
302                 
303                 col = split.column()
304                 col.itemR(con, "rotate_like_z", text="Z")
305                 sub = col.column()
306                 sub.active = con.rotate_like_z
307                 sub.itemR(con, "invert_z", text="Invert")
308
309                 layout.itemR(con, "offset")
310                 
311                 self.space_template(layout, con)
312                 
313         def COPY_LOCATION(self, context, layout, con):
314                 self.target_template(layout, con)
315                 
316                 split = layout.split()
317                 
318                 col = split.column()
319                 col.itemR(con, "locate_like_x", text="X")
320                 sub = col.column()
321                 sub.active = con.locate_like_x
322                 sub.itemR(con, "invert_x", text="Invert")
323                 
324                 col = split.column()
325                 col.itemR(con, "locate_like_y", text="Y")
326                 sub = col.column()
327                 sub.active = con.locate_like_y
328                 sub.itemR(con, "invert_y", text="Invert")
329                 
330                 col = split.column()
331                 col.itemR(con, "locate_like_z", text="Z")
332                 sub = col.column()
333                 sub.active = con.locate_like_z
334                 sub.itemR(con, "invert_z", text="Invert")
335
336                 layout.itemR(con, "offset")
337                         
338                 self.space_template(layout, con)
339                 
340         def COPY_SCALE(self, context, layout, con):
341                 self.target_template(layout, con)
342                 
343                 row = layout.row(align=True)
344                 row.itemR(con, "size_like_x", text="X")
345                 row.itemR(con, "size_like_y", text="Y")
346                 row.itemR(con, "size_like_z", text="Z")
347
348                 layout.itemR(con, "offset")
349                 
350                 self.space_template(layout, con)
351                 
352         #def SCRIPT(self, context, layout, con):
353         
354         def ACTION(self, context, layout, con):
355                 self.target_template(layout, con)
356                 
357                 layout.itemR(con, "action")
358                 layout.itemR(con, "transform_channel")
359
360                 split = layout.split()
361         
362                 col = split.column(align=True)
363                 col.itemR(con, "start_frame", text="Start")
364                 col.itemR(con, "end_frame", text="End")
365                 
366                 col = split.column(align=True)
367                 col.itemR(con, "minimum", text="Min")
368                 col.itemR(con, "maximum", text="Max")
369                 
370                 row = layout.row()
371                 row.itemL(text="Convert:")
372                 row.itemR(con, "owner_space", text="")
373         
374         def LOCKED_TRACK(self, context, layout, con):
375                 self.target_template(layout, con)
376                 
377                 row = layout.row()
378                 row.itemL(text="To:")
379                 row.itemR(con, "track", expand=True)
380                 
381                 row = layout.row()
382                 row.itemL(text="Lock:")
383                 row.itemR(con, "locked", expand=True)
384                 
385         def LIMIT_DISTANCE(self, context, layout, con):
386                 self.target_template(layout, con)
387                 
388                 col = layout.column(align=True);
389                 col.itemR(con, "distance")
390                 col.itemO("constraint.limitdistance_reset")
391                 
392                 row = layout.row()
393                 row.itemL(text="Clamp Region:")
394                 row.itemR(con, "limit_mode", text="")
395                 
396         def STRETCH_TO(self, context, layout, con):
397                 self.target_template(layout, con)
398                 
399                 row = layout.row()
400                 row.itemR(con, "original_length", text="Rest Length")
401                 row.itemO("constraint.stretchto_reset", text="Reset")
402                 
403                 col = layout.column()
404                 col.itemR(con, "bulge", text="Volume Variation")
405                 
406                 row = layout.row()
407                 row.itemL(text="Volume:")
408                 row.itemR(con, "volume", expand=True)
409                 row.itemL(text="Plane:")
410                 row.itemR(con, "keep_axis", expand=True)
411                 
412         def FLOOR(self, context, layout, con):
413                 self.target_template(layout, con)
414                 
415                 row = layout.row()
416                 row.itemR(con, "sticky")
417                 row.itemR(con, "use_rotation")
418                 
419                 layout.itemR(con, "offset")
420                 
421                 row = layout.row()
422                 row.itemL(text="Min/Max:")
423                 row.itemR(con, "floor_location", expand=True)
424                 
425         def RIGID_BODY_JOINT(self, context, layout, con):
426                 self.target_template(layout, con)
427                 
428                 layout.itemR(con, "pivot_type")
429                 layout.itemR(con, "child")
430                 
431                 row = layout.row()
432                 row.itemR(con, "disable_linked_collision", text="No Collision")
433                 row.itemR(con, "draw_pivot", text="Display Pivot")
434                 
435                 split = layout.split()
436                 
437                 col = split.column(align=True)
438                 col.itemL(text="Pivot:")
439                 col.itemR(con, "pivot_x", text="X")
440                 col.itemR(con, "pivot_y", text="Y")
441                 col.itemR(con, "pivot_z", text="Z")
442                 
443                 col = split.column(align=True)
444                 col.itemL(text="Axis:")
445                 col.itemR(con, "axis_x", text="X")
446                 col.itemR(con, "axis_y", text="Y")
447                 col.itemR(con, "axis_z", text="Z")
448                 
449                 #Missing: Limit arrays (not wrapped in RNA yet) 
450         
451         def CLAMP_TO(self, context, layout, con):
452                 self.target_template(layout, con)
453                 
454                 row = layout.row()
455                 row.itemL(text="Main Axis:")
456                 row.itemR(con, "main_axis", expand=True)
457                 
458                 row = layout.row()
459                 row.itemR(con, "cyclic")
460                 
461         def TRANSFORM(self, context, layout, con):
462                 self.target_template(layout, con)
463                 
464                 layout.itemR(con, "extrapolate_motion", text="Extrapolate")
465                 
466                 split = layout.split()
467                 
468                 col = split.column()
469                 col.itemL(text="Source:")
470                 col.row().itemR(con, "map_from", expand=True)
471                 
472                 sub = col.row(align=True)
473                 sub.itemL(text="X:")
474                 sub.itemR(con, "from_min_x", text="")
475                 sub.itemR(con, "from_max_x", text="")
476                 
477                 sub = col.row(align=True)
478                 sub.itemL(text="Y:")
479                 sub.itemR(con, "from_min_y", text="")
480                 sub.itemR(con, "from_max_y", text="")
481                 
482                 sub = col.row(align=True)
483                 sub.itemL(text="Z:")
484                 sub.itemR(con, "from_min_z", text="")
485                 sub.itemR(con, "from_max_z", text="")
486                 
487                 split = layout.split()
488                 
489                 col = split.column()
490                 col.itemL(text="Destination:")
491                 col.row().itemR(con, "map_to", expand=True)
492
493                 sub = col.row(align=True)
494                 sub.itemR(con, "map_to_x_from", text="")
495                 sub.itemR(con, "to_min_x", text="")
496                 sub.itemR(con, "to_max_x", text="")
497                 
498                 sub = col.row(align=True)
499                 sub.itemR(con, "map_to_y_from", text="")
500                 sub.itemR(con, "to_min_y", text="")
501                 sub.itemR(con, "to_max_y", text="")
502                 
503                 sub = col.row(align=True)
504                 sub.itemR(con, "map_to_z_from", text="")
505                 sub.itemR(con, "to_min_z", text="")
506                 sub.itemR(con, "to_max_z", text="")
507                 
508                 self.space_template(layout, con)
509                 
510         def SHRINKWRAP (self, context, layout, con):
511                 self.target_template(layout, con)
512                 
513                 layout.itemR(con, "distance")
514                 layout.itemR(con, "shrinkwrap_type")
515                 
516                 if con.shrinkwrap_type == 'PROJECT':
517                         row = layout.row(align=True)
518                         row.itemR(con, "axis_x")
519                         row.itemR(con, "axis_y")
520                         row.itemR(con, "axis_z")
521                 
522 class OBJECT_PT_constraints(ConstraintButtonsPanel):
523         __label__ = "Constraints"
524         __context__ = "constraint"
525
526         def poll(self, context):
527                 return (context.object)
528                 
529         def draw(self, context):
530                 layout = self.layout
531                 ob = context.object
532
533                 row = layout.row()
534                 row.item_menu_enumO("object.constraint_add", "type")
535                 row.itemL();
536
537                 for con in ob.constraints:
538                         self.draw_constraint(context, con)
539
540 class BONE_PT_constraints(ConstraintButtonsPanel):
541         __label__ = "Constraints"
542         __context__ = "bone_constraint"
543
544         def poll(self, context):
545                 ob = context.object
546                 return (ob and ob.type == 'ARMATURE' and context.bone)
547                 
548         def draw(self, context):
549                 layout = self.layout
550                 
551                 ob = context.object
552                 pchan = ob.pose.pose_channels[context.bone.name]
553
554                 row = layout.row()
555                 row.item_menu_enumO("pose.constraint_add", "type")
556                 row.itemL();
557
558                 for con in pchan.constraints:
559                         self.draw_constraint(context, con)
560
561 bpy.types.register(OBJECT_PT_constraints)
562 bpy.types.register(BONE_PT_constraints)