Merge with 2.5 -r 21619:21756.
[blender.git] / release / ui / buttons_object_constraint.py
1
2 import bpy
3
4 class ConstraintButtonsPanel(bpy.types.Panel):
5         __space_type__ = "BUTTONS_WINDOW"
6         __region_type__ = "WINDOW"
7         __context__ = "constraint"
8
9         def draw_constraint(self, con):
10                 layout = self.layout
11                 box = layout.template_constraint(con)
12
13                 if box:
14                         if con.type == "CHILD_OF":
15                                 self.child_of(box, con)
16                         elif con.type == "TRACK_TO":
17                                 self.track_to(box, con)
18                         elif con.type == "IK":
19                                 self.ik(box, con)
20                         elif con.type == "FOLLOW_PATH":
21                                 self.follow_path(box, con)
22                         elif con.type == "LIMIT_ROTATION":
23                                 self.limit_rotation(box, con)
24                         elif con.type == "LIMIT_LOCATION":
25                                 self.limit_location(box, con)
26                         elif con.type == "LIMIT_SCALE":
27                                 self.limit_scale(box, con)
28                         elif con.type == "COPY_ROTATION":
29                                 self.copy_rotation(box, con)
30                         elif con.type == "COPY_LOCATION":
31                                 self.copy_location(box, con)
32                         elif con.type == "COPY_SCALE":
33                                 self.copy_scale(box, con)
34                         #elif con.type == "SCRIPT":
35                         #       self.script(box, con)
36                         elif con.type == "ACTION":
37                                 self.action(box, con)
38                         elif con.type == "LOCKED_TRACK":
39                                 self.locked_track(box, con)
40                         elif con.type == "LIMIT_DISTANCE":
41                                 self.limit_distance(box, con)
42                         elif con.type == "STRETCH_TO":
43                                 self.stretch_to(box, con)
44                         elif con.type == "FLOOR":
45                                 self.floor(box, con)
46                         elif con.type == "RIGID_BODY_JOINT":
47                                 self.rigid_body(box, con)
48                         elif con.type == "CLAMP_TO":
49                                 self.clamp_to(box, con)
50                         elif con.type == "TRANSFORM":
51                                 self.transform(box, con)
52                         elif con.type == "SHRINKWRAP":
53                                 self.shrinkwrap(box, con)
54                                 
55                         # show/key buttons here are most likely obsolete now, with
56                         # keyframing functionality being part of every button
57                         if con.type not in ("RIGID_BODY_JOINT", "NULL"):
58                                 box.itemR(con, "influence")
59         
60         def space_template(self, layout, con, target=True, owner=True):
61                 if target or owner:
62                         row = layout.row()
63
64                         row.itemL(text="Convert:")
65
66                         if target:
67                                 row.itemR(con, "target_space", text="")
68
69                         if target and owner:
70                                 row.itemL(icon="ICON_ARROW_LEFTRIGHT")
71
72                         if owner:
73                                 row.itemR(con, "owner_space", text="")
74                         
75         def target_template(self, layout, con, subtargets=True):
76                 layout.itemR(con, "target") # XXX limiting settings for only 'curves' or some type of object
77                 
78                 if con.target and subtargets:
79                         if con.target.type == "ARMATURE":
80                                 layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone")
81                                 
82                                 if con.type == 'COPY_LOCATION':
83                                         row = layout.row()
84                                         row.itemL(text="Head/Tail:")
85                                         row.itemR(con, "head_tail", text="")
86                         elif con.target.type in ("MESH", "LATTICE"):
87                                 layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
88         
89         def child_of(self, layout, con):
90                 self.target_template(layout, con)
91
92                 split = layout.split()
93                 
94                 sub = split.column()
95                 sub.itemL(text="Location:")
96                 sub.itemR(con, "locationx", text="X")
97                 sub.itemR(con, "locationy", text="Y")
98                 sub.itemR(con, "locationz", text="Z")
99                 
100                 sub = split.column()
101                 sub.itemL(text="Rotation:")
102                 sub.itemR(con, "rotationx", text="X")
103                 sub.itemR(con, "rotationy", text="Y")
104                 sub.itemR(con, "rotationz", text="Z")
105                 
106                 sub = split.column()
107                 sub.itemL(text="Scale:")
108                 sub.itemR(con, "sizex", text="X")
109                 sub.itemR(con, "sizey", text="Y")
110                 sub.itemR(con, "sizez", text="Z")
111                 
112                 row = layout.row()
113                 row.itemO("constraint.childof_set_inverse")
114                 row.itemO("constraint.childof_clear_inverse")
115                 
116         def track_to(self, layout, con):
117                 self.target_template(layout, con)
118                 
119                 row = layout.row()
120                 row.itemL(text="To:")
121                 row.itemR(con, "track", expand=True)
122                 
123                 row = layout.row()
124                 #row.itemR(con, "up", text="Up", expand=True) # XXX: up and expand don't play nice together
125                 row.itemR(con, "up", text="Up")
126                 row.itemR(con, "target_z")
127                 
128                 self.space_template(layout, con)
129                 
130         def ik(self, layout, con):
131                 self.target_template(layout, con)
132                 
133                 layout.itemR(con, "pole_target")
134                 if con.pole_target and con.pole_target.type == "ARMATURE":
135                         layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
136                 
137                 col = layout.column_flow()
138                 col.itemR(con, "iterations")
139                 col.itemR(con, "pole_angle")
140                 col.itemR(con, "weight")
141                 col.itemR(con, "orient_weight")
142                 col.itemR(con, "chain_length")
143                 
144                 col = layout.column_flow()
145                 col.itemR(con, "tail")
146                 col.itemR(con, "rotation")
147                 col.itemR(con, "targetless")
148                 col.itemR(con, "stretch")
149                 
150         def follow_path(self, layout, con):
151                 self.target_template(layout, con)
152                 
153                 row = layout.row()
154                 row.itemR(con, "curve_follow")
155                 row.itemR(con, "offset")
156                 
157                 row = layout.row()
158                 row.itemL(text="Forward:")
159                 row.itemR(con, "forward", expand=True)
160                 
161                 row = layout.row()
162                 row.itemR(con, "up", text="Up")
163                 row.itemL()
164                 
165         def limit_rotation(self, layout, con):
166                 
167                 split = layout.split()
168                 
169                 col = split.column()
170                 col.itemR(con, "use_limit_x")
171                 colsub = col.column()
172                 colsub.active = con.use_limit_x
173                 colsub.itemR(con, "minimum_x", text="Min")
174                 colsub.itemR(con, "maximum_x", text="Max")
175                 
176                 col = split.column()
177                 col.itemR(con, "use_limit_y")
178                 colsub = col.column()
179                 colsub.active = con.use_limit_y
180                 colsub.itemR(con, "minimum_y", text="Min")
181                 colsub.itemR(con, "maximum_y", text="Max")
182                 
183                 col = split.column()
184                 col.itemR(con, "use_limit_z")
185                 colsub = col.column()
186                 colsub.active = con.use_limit_z
187                 colsub.itemR(con, "minimum_z", text="Min")
188                 colsub.itemR(con, "maximum_z", text="Max")
189                 
190                 row = layout.row()
191                 row.itemR(con, "limit_transform")
192                 row.itemL()
193                 
194                 row = layout.row()
195                 row.itemL(text="Convert:")
196                 row.itemR(con, "owner_space", text="")
197                 
198         def limit_location(self, layout, con):
199                 split = layout.split()
200                 
201                 col = split.column()
202                 col.itemR(con, "use_minimum_x")
203                 colsub = col.column()
204                 colsub.active = con.use_minimum_x
205                 colsub.itemR(con, "minimum_x", text="")
206                 col.itemR(con, "use_maximum_x")
207                 colsub = col.column()
208                 colsub.active = con.use_maximum_x
209                 colsub.itemR(con, "maximum_x", text="")
210                 
211                 col = split.column()
212                 col.itemR(con, "use_minimum_y")
213                 colsub = col.column()
214                 colsub.active = con.use_minimum_y
215                 colsub.itemR(con, "minimum_y", text="")
216                 col.itemR(con, "use_maximum_y")
217                 colsub = col.column()
218                 colsub.active = con.use_maximum_y
219                 colsub.itemR(con, "maximum_y", text="")
220                 
221                 col = split.column()
222                 col.itemR(con, "use_minimum_z")
223                 colsub = col.column()
224                 colsub.active = con.use_minimum_z
225                 colsub.itemR(con, "minimum_z", text="")
226                 col.itemR(con, "use_maximum_z")
227                 colsub = col.column()
228                 colsub.active = con.use_maximum_z
229                 colsub.itemR(con, "maximum_z", text="")
230         
231                 row = layout.row()
232                 row.itemR(con, "limit_transform")
233                 row.itemL()
234                 
235                 row = layout.row()
236                 row.itemL(text="Convert:")
237                 row.itemR(con, "owner_space", text="")
238                 
239         def limit_scale(self, layout, con):
240                 split = layout.split()
241
242                 col = split.column()
243                 col.itemR(con, "use_minimum_x")
244                 colsub = col.column()
245                 colsub.active = con.use_minimum_x
246                 colsub.itemR(con, "minimum_x", text="")
247                 col.itemR(con, "use_maximum_x")
248                 colsub = col.column()
249                 colsub.active = con.use_maximum_x
250                 colsub.itemR(con, "maximum_x", text="")
251                 
252                 col = split.column()
253                 col.itemR(con, "use_minimum_y")
254                 colsub = col.column()
255                 colsub.active = con.use_minimum_y
256                 colsub.itemR(con, "minimum_y", text="")
257                 col.itemR(con, "use_maximum_y")
258                 colsub = col.column()
259                 colsub.active = con.use_maximum_y
260                 colsub.itemR(con, "maximum_y", text="")
261                 
262                 col = split.column()
263                 col.itemR(con, "use_minimum_z")
264                 colsub = col.column()
265                 colsub.active = con.use_minimum_z
266                 colsub.itemR(con, "minimum_z", text="")
267                 col.itemR(con, "use_maximum_z")
268                 colsub = col.column()
269                 colsub.active = con.use_maximum_z
270                 colsub.itemR(con, "maximum_z", text="")
271                 
272                 row = layout.row()
273                 row.itemR(con, "limit_transform")
274                 row.itemL()
275                 
276                 row = layout.row()
277                 row.itemL(text="Convert:")
278                 row.itemR(con, "owner_space", text="")
279         
280         def copy_rotation(self, layout, con):
281                 self.target_template(layout, con)
282                 
283                 split = layout.split()
284                 
285                 col = split.column()
286                 col.itemR(con, "rotate_like_x", text="X")
287                 colsub = col.column()
288                 colsub.active = con.rotate_like_x
289                 colsub.itemR(con, "invert_x", text="Invert")
290                 
291                 col = split.column()
292                 col.itemR(con, "rotate_like_y", text="Y")
293                 colsub = col.column()
294                 colsub.active = con.rotate_like_y
295                 colsub.itemR(con, "invert_y", text="Invert")
296                 
297                 col = split.column()
298                 col.itemR(con, "rotate_like_z", text="Z")
299                 colsub = col.column()
300                 colsub.active = con.rotate_like_z
301                 colsub.itemR(con, "invert_z", text="Invert")
302
303                 layout.itemR(con, "offset")
304                 
305                 self.space_template(layout, con)
306                 
307         def copy_location(self, layout, con):
308                 self.target_template(layout, con)
309                 
310                 split = layout.split()
311                 
312                 col = split.column()
313                 col.itemR(con, "locate_like_x", text="X")
314                 colsub = col.column()
315                 colsub.active = con.locate_like_x
316                 colsub.itemR(con, "invert_x", text="Invert")
317                 
318                 col = split.column()
319                 col.itemR(con, "locate_like_y", text="Y")
320                 colsub = col.column()
321                 colsub.active = con.locate_like_y
322                 colsub.itemR(con, "invert_y", text="Invert")
323                 
324                 col = split.column()
325                 col.itemR(con, "locate_like_z", text="Z")
326                 colsub = col.column()
327                 colsub.active = con.locate_like_z
328                 colsub.itemR(con, "invert_z", text="Invert")
329
330                 layout.itemR(con, "offset")
331                         
332                 self.space_template(layout, con)
333                 
334         def copy_scale(self, layout, con):
335                 self.target_template(layout, con)
336                 
337                 row = layout.row(align=True)
338                 row.itemR(con, "size_like_x", text="X")
339                 row.itemR(con, "size_like_y", text="Y")
340                 row.itemR(con, "size_like_z", text="Z")
341
342                 layout.itemR(con, "offset")
343                 
344                 self.space_template(layout, con)
345                 
346         #def script(self, layout, con):
347         
348         def action(self, layout, con):
349                 self.target_template(layout, con)
350                 
351                 layout.itemR(con, "action")
352                 layout.itemR(con, "transform_channel")
353
354                 split = layout.split()
355         
356                 col = split.column(align=True)
357                 col.itemR(con, "start_frame", text="Start")
358                 col.itemR(con, "end_frame", text="End")
359                 
360                 col = split.column(align=True)
361                 col.itemR(con, "minimum", text="Min")
362                 col.itemR(con, "maximum", text="Max")
363                 
364                 row = layout.row()
365                 row.itemL(text="Convert:")
366                 row.itemR(con, "owner_space", text="")
367         
368         def locked_track(self, layout, con):
369                 self.target_template(layout, con)
370                 
371                 row = layout.row()
372                 row.itemL(text="To:")
373                 row.itemR(con, "track", expand=True)
374                 
375                 row = layout.row()
376                 row.itemL(text="Lock:")
377                 row.itemR(con, "locked", expand=True)
378                 
379         def limit_distance(self, layout, con):
380                 self.target_template(layout, con)
381                 
382                 layout.itemR(con, "distance")
383                 
384                 row = layout.row()
385                 row.itemL(text="Clamp Region:")
386                 row.itemR(con, "limit_mode", text="")
387                 #Missing: Recalculate Button
388                 
389         def stretch_to(self, layout, con):
390                 self.target_template(layout, con)
391                 
392                 row = layout.row()
393                 row.itemR(con, "original_length", text="Rest Length")
394                 row.itemR(con, "bulge", text="Volume Variation")
395                 
396                 row = layout.row()
397                 row.itemL(text="Volume:")
398                 row.itemR(con, "volume", expand=True)
399                 row.itemL(text="Plane:")
400                 row.itemR(con, "keep_axis", expand=True)
401                 #Missing: Recalculate Button
402                 
403         def floor(self, layout, con):
404                 self.target_template(layout, con)
405                 
406                 row = layout.row()
407                 row.itemR(con, "sticky")
408                 row.itemR(con, "use_rotation")
409                 
410                 layout.itemR(con, "offset")
411                 
412                 row = layout.row()
413                 row.itemL(text="Min/Max:")
414                 row.itemR(con, "floor_location", expand=True)
415                 
416         def rigid_body(self, layout, con):
417                 self.target_template(layout, con)
418                 
419                 layout.itemR(con, "pivot_type")
420                 layout.itemR(con, "child")
421                 
422                 row = layout.row()
423                 row.itemR(con, "disable_linked_collision", text="No Collision")
424                 row.itemR(con, "draw_pivot")
425                 
426                 split = layout.split()
427                 
428                 col = split.column()
429                 col.itemR(con, "pivot_x")
430                 col.itemR(con, "pivot_y")
431                 col.itemR(con, "pivot_z")
432                 
433                 col = split.column()
434                 col.itemR(con, "axis_x")
435                 col.itemR(con, "axis_y")
436                 col.itemR(con, "axis_z")
437                 
438                 #Missing: Limit arrays (not wrapped in RNA yet) 
439         
440         def clamp_to(self, layout, con):
441                 self.target_template(layout, con)
442                 
443                 row = layout.row()
444                 row.itemL(text="Main Axis:")
445                 row.itemR(con, "main_axis", expand=True)
446                 
447                 row = layout.row()
448                 row.itemR(con, "cyclic")
449                 
450         def transform(self, layout, con):
451                 self.target_template(layout, con)
452                 
453                 layout.itemR(con, "extrapolate_motion", text="Extrapolate")
454                 
455                 split = layout.split()
456                 
457                 col = split.column()
458                 col.itemL(text="Source:")
459                 col.row().itemR(con, "map_from", expand=True)
460                 
461                 sub = col.row(align=True)
462                 sub.itemL(text="X:")
463                 sub.itemR(con, "from_min_x", text="")
464                 sub.itemR(con, "from_max_x", text="")
465                 
466                 sub = col.row(align=True)
467                 sub.itemL(text="Y:")
468                 sub.itemR(con, "from_min_y", text="")
469                 sub.itemR(con, "from_max_y", text="")
470                 
471                 sub = col.row(align=True)
472                 sub.itemL(text="Z:")
473                 sub.itemR(con, "from_min_z", text="")
474                 sub.itemR(con, "from_max_z", text="")
475                 
476                 split = layout.split()
477                 
478                 col = split.column()
479                 col.itemL(text="Destination:")
480                 col.row().itemR(con, "map_to", expand=True)
481
482                 sub = col.row(align=True)
483                 sub.itemR(con, "map_to_x_from", text="")
484                 sub.itemR(con, "to_min_x", text="")
485                 sub.itemR(con, "to_max_x", text="")
486                 
487                 sub = col.row(align=True)
488                 sub.itemR(con, "map_to_y_from", text="")
489                 sub.itemR(con, "to_min_y", text="")
490                 sub.itemR(con, "to_max_y", text="")
491                 
492                 sub = col.row(align=True)
493                 sub.itemR(con, "map_to_z_from", text="")
494                 sub.itemR(con, "to_min_z", text="")
495                 sub.itemR(con, "to_max_z", text="")
496                 
497                 self.space_template(layout, con)
498                 
499         def shrinkwrap (self, layout, con):
500                 self.target_template(layout, con)
501                 
502                 layout.itemR(con, "distance")
503                 layout.itemR(con, "shrinkwrap_type")
504                 
505                 if con.shrinkwrap_type == "PROJECT":
506                         row = layout.row(align=True)
507                         row.itemR(con, "axis_x")
508                         row.itemR(con, "axis_y")
509                         row.itemR(con, "axis_z")
510                 
511 class OBJECT_PT_constraints(ConstraintButtonsPanel):
512         __idname__ = "OBJECT_PT_constraints"
513         __label__ = "Constraints"
514         __context__ = "constraint"
515
516         def poll(self, context):
517                 return (context.object != None)
518                 
519         def draw(self, context):
520                 ob = context.object
521                 layout = self.layout
522
523                 row = layout.row()
524                 row.item_menu_enumO("object.constraint_add", "type")
525                 row.itemL();
526
527                 for con in ob.constraints:
528                         self.draw_constraint(con)
529
530 class BONE_PT_constraints(ConstraintButtonsPanel):
531         __idname__ = "BONE_PT_constraints"
532         __label__ = "Constraints"
533         __context__ = "bone"
534
535         def poll(self, context):
536                 ob = context.object
537                 return (ob and ob.type == "ARMATURE" and context.bone)
538                 
539         def draw(self, context):
540                 ob = context.object
541                 pchan = ob.pose.pose_channels[context.bone.name]
542                 layout = self.layout
543
544                 row = layout.row()
545                 row.item_menu_enumO("pose.constraint_add", "type")
546                 row.itemL();
547
548                 for con in pchan.constraints:
549                         self.draw_constraint(con)
550
551 bpy.types.register(OBJECT_PT_constraints)
552 bpy.types.register(BONE_PT_constraints)