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