3dc1b47b3ef8f8e407e42e643a92b8c7f8f4ffae
[blender.git] / release / scripts / ui / properties_data_armature.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from rna_prop_ui import PropertyPanel
22
23 narrowui = bpy.context.user_preferences.view.properties_width_check
24
25
26 class DataButtonsPanel():
27     bl_space_type = 'PROPERTIES'
28     bl_region_type = 'WINDOW'
29     bl_context = "data"
30
31     @staticmethod
32     def poll(context):
33         return context.armature
34
35
36 class DATA_PT_context_arm(DataButtonsPanel, bpy.types.Panel):
37     bl_label = ""
38     bl_show_header = False
39
40     def draw(self, context):
41         layout = self.layout
42
43         ob = context.object
44         arm = context.armature
45         space = context.space_data
46         wide_ui = context.region.width > narrowui
47
48         if wide_ui:
49             split = layout.split(percentage=0.65)
50             if ob:
51                 split.template_ID(ob, "data")
52                 split.separator()
53             elif arm:
54                 split.template_ID(space, "pin_id")
55                 split.separator()
56         else:
57             layout.template_ID(ob, "data")
58
59
60 class DATA_PT_custom_props_arm(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
61     _context_path = "object.data"
62
63
64 class DATA_PT_skeleton(DataButtonsPanel, bpy.types.Panel):
65     bl_label = "Skeleton"
66
67     def draw(self, context):
68         layout = self.layout
69
70         arm = context.armature
71         wide_ui = context.region.width > narrowui
72
73         if wide_ui:
74             layout.prop(arm, "pose_position", expand=True)
75         else:
76             layout.prop(arm, "pose_position", text="")
77
78         split = layout.split()
79
80         col = split.column()
81         col.label(text="Layers:")
82         col.prop(arm, "layer", text="")
83         col.label(text="Protected Layers:")
84         col.prop(arm, "layer_protection", text="")
85
86         col.label(text="Deform:")
87
88         split = layout.split()
89
90         col = split.column()
91         col.prop(arm, "deform_vertexgroups", text="Vertex Groups")
92         col.prop(arm, "deform_envelope", text="Envelopes")
93
94         if wide_ui:
95             col = split.column()
96         col.prop(arm, "deform_quaternion", text="Quaternion")
97
98
99 class DATA_PT_display(DataButtonsPanel, bpy.types.Panel):
100     bl_label = "Display"
101
102     def draw(self, context):
103         layout = self.layout
104
105         ob = context.object
106         arm = context.armature
107         wide_ui = context.region.width > narrowui
108
109         if wide_ui:
110             layout.row().prop(arm, "drawtype", expand=True)
111         else:
112             layout.row().prop(arm, "drawtype", text="")
113
114         split = layout.split()
115
116         col = split.column()
117         col.prop(arm, "draw_names", text="Names")
118         col.prop(arm, "draw_axes", text="Axes")
119         col.prop(arm, "draw_custom_bone_shapes", text="Shapes")
120
121         if wide_ui:
122             col = split.column()
123         col.prop(arm, "draw_group_colors", text="Colors")
124         col.prop(ob, "x_ray", text="X-Ray")
125         col.prop(arm, "delay_deform", text="Delay Refresh")
126
127
128 class DATA_PT_bone_groups(DataButtonsPanel, bpy.types.Panel):
129     bl_label = "Bone Groups"
130
131     @staticmethod
132     def poll(context):
133         return (context.object and context.object.type == 'ARMATURE' and context.object.pose)
134
135     def draw(self, context):
136         layout = self.layout
137
138         ob = context.object
139         pose = ob.pose
140         wide_ui = context.region.width > narrowui
141
142         row = layout.row()
143         row.template_list(pose, "bone_groups", pose, "active_bone_group_index", rows=2)
144
145         col = row.column(align=True)
146         col.active = (ob.proxy is None)
147         col.operator("pose.group_add", icon='ZOOMIN', text="")
148         col.operator("pose.group_remove", icon='ZOOMOUT', text="")
149
150         group = pose.active_bone_group
151         if group:
152             col = layout.column()
153             col.active = (ob.proxy is None)
154             col.prop(group, "name")
155
156             split = layout.split()
157             split.active = (ob.proxy is None)
158
159             col = split.column()
160             col.prop(group, "color_set")
161             if group.color_set:
162                 if wide_ui:
163                     col = split.column()
164                 col.template_triColorSet(group, "colors")
165
166         row = layout.row()
167         row.active = (ob.proxy is None)
168
169         sub = row.row(align=True)
170         sub.operator("pose.group_assign", text="Assign")
171         sub.operator("pose.group_unassign", text="Remove") #row.operator("pose.bone_group_remove_from", text="Remove")
172
173         sub = row.row(align=True)
174         sub.operator("pose.group_select", text="Select")
175         sub.operator("pose.group_deselect", text="Deselect")
176
177
178 # TODO: this panel will soon be depreceated too
179 class DATA_PT_ghost(DataButtonsPanel, bpy.types.Panel):
180     bl_label = "Ghost"
181
182     def draw(self, context):
183         layout = self.layout
184
185         arm = context.armature
186         wide_ui = context.region.width > narrowui
187
188         if wide_ui:
189             layout.prop(arm, "ghost_type", expand=True)
190         else:
191             layout.prop(arm, "ghost_type", text="")
192
193         split = layout.split()
194
195         col = split.column()
196
197         sub = col.column(align=True)
198         if arm.ghost_type == 'RANGE':
199             sub.prop(arm, "ghost_frame_start", text="Start")
200             sub.prop(arm, "ghost_frame_end", text="End")
201             sub.prop(arm, "ghost_size", text="Step")
202         elif arm.ghost_type == 'CURRENT_FRAME':
203             sub.prop(arm, "ghost_step", text="Range")
204             sub.prop(arm, "ghost_size", text="Step")
205
206         if wide_ui:
207             col = split.column()
208         col.label(text="Display:")
209         col.prop(arm, "ghost_only_selected", text="Selected Only")
210
211
212 class DATA_PT_iksolver_itasc(DataButtonsPanel, bpy.types.Panel):
213     bl_label = "iTaSC parameters"
214     bl_default_closed = True
215
216     @staticmethod
217     def poll(context):
218         ob = context.object
219         return (ob and ob.pose)
220
221     def draw(self, context):
222         layout = self.layout
223
224         ob = context.object
225
226         itasc = ob.pose.ik_param
227         wide_ui = (context.region.width > narrowui)
228
229         row = layout.row()
230         row.prop(ob.pose, "ik_solver")
231
232         if itasc:
233             layout.prop(itasc, "mode", expand=True)
234             simulation = (itasc.mode == 'SIMULATION')
235             if simulation:
236                 layout.label(text="Reiteration:")
237                 layout.prop(itasc, "reiteration", expand=True)
238
239             split = layout.split()
240             split.active = not simulation or itasc.reiteration != 'NEVER'
241             col = split.column()
242             col.prop(itasc, "precision")
243
244             if wide_ui:
245                 col = split.column()
246             col.prop(itasc, "num_iter")
247
248
249             if simulation:
250                 layout.prop(itasc, "auto_step")
251                 row = layout.row()
252                 if itasc.auto_step:
253                     row.prop(itasc, "min_step", text="Min")
254                     row.prop(itasc, "max_step", text="Max")
255                 else:
256                     row.prop(itasc, "num_step")
257
258             layout.prop(itasc, "solver")
259             if simulation:
260                 layout.prop(itasc, "feedback")
261                 layout.prop(itasc, "max_velocity")
262             if itasc.solver == 'DLS':
263                 row = layout.row()
264                 row.prop(itasc, "dampmax", text="Damp", slider=True)
265                 row.prop(itasc, "dampeps", text="Eps", slider=True)
266
267 from properties_animviz import MotionPathButtonsPanel, OnionSkinButtonsPanel
268
269 class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
270     #bl_label = "Bones Motion Paths"
271     bl_context = "data"
272
273     @staticmethod
274     def poll(context):
275         # XXX: include posemode check?
276         return (context.object) and (context.armature)
277
278     def draw(self, context):
279         layout = self.layout
280
281         ob = context.object
282         wide_ui = context.region.width > narrowui
283
284         self.draw_settings(context, ob.pose.animation_visualisation, wide_ui, bones=True)
285
286         layout.separator()
287
288         split = layout.split()
289
290         col = split.column()
291         col.operator("pose.paths_calculate", text="Calculate Paths")
292
293         if wide_ui:
294             col = split.column()
295         col.operator("pose.paths_clear", text="Clear Paths")
296
297
298 class DATA_PT_onion_skinning(OnionSkinButtonsPanel): #, bpy.types.Panel): # inherit from panel when ready
299     #bl_label = "Bones Onion Skinning"
300     bl_context = "data"
301
302     @staticmethod
303     def poll(context):
304         # XXX: include posemode check?
305         return (context.object) and (context.armature)
306
307     def draw(self, context):
308         layout = self.layout
309
310         ob = context.object
311         wide_ui = context.region.width > narrowui
312
313         self.draw_settings(context, ob.pose.animation_visualisation, wide_ui, bones=True)
314
315 def register():
316     pass
317
318
319 def unregister():
320     pass
321
322 if __name__ == "__main__":
323     register()