2f5ffd0803f10d98d8ec3c0c190d41dae43e70b7
[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
24 class DataButtonsPanel():
25     bl_space_type = 'PROPERTIES'
26     bl_region_type = 'WINDOW'
27     bl_context = "data"
28
29     @staticmethod
30     def poll(context):
31         return context.armature
32
33
34 class DATA_PT_context_arm(DataButtonsPanel, bpy.types.Panel):
35     bl_label = ""
36     bl_show_header = False
37
38     def draw(self, context):
39         layout = self.layout
40
41         ob = context.object
42         arm = context.armature
43         space = context.space_data
44
45         split = layout.split(percentage=0.65)
46         if ob:
47             split.template_ID(ob, "data")
48             split.separator()
49         elif arm:
50             split.template_ID(space, "pin_id")
51             split.separator()
52
53
54 class DATA_PT_custom_props_arm(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
55     _context_path = "object.data"
56
57
58 class DATA_PT_skeleton(DataButtonsPanel, bpy.types.Panel):
59     bl_label = "Skeleton"
60
61     def draw(self, context):
62         layout = self.layout
63
64         arm = context.armature
65
66         layout.prop(arm, "pose_position", expand=True)
67
68         split = layout.split()
69
70         col = split.column()
71         col.label(text="Layers:")
72         col.prop(arm, "layer", text="")
73         col.label(text="Protected Layers:")
74         col.prop(arm, "layer_protection", text="")
75
76         col.label(text="Deform:")
77
78         split = layout.split()
79
80         col = split.column()
81         col.prop(arm, "deform_vertexgroups", text="Vertex Groups")
82         col.prop(arm, "deform_envelope", text="Envelopes")
83
84         col = split.column()
85         col.prop(arm, "deform_quaternion", text="Quaternion")
86
87
88 class DATA_PT_display(DataButtonsPanel, bpy.types.Panel):
89     bl_label = "Display"
90
91     def draw(self, context):
92         layout = self.layout
93
94         ob = context.object
95         arm = context.armature
96
97         layout.row().prop(arm, "drawtype", expand=True)
98
99         split = layout.split()
100
101         col = split.column()
102         col.prop(arm, "draw_names", text="Names")
103         col.prop(arm, "draw_axes", text="Axes")
104         col.prop(arm, "draw_custom_bone_shapes", text="Shapes")
105
106         col = split.column()
107         col.prop(arm, "draw_group_colors", text="Colors")
108         col.prop(ob, "x_ray", text="X-Ray")
109         col.prop(arm, "delay_deform", text="Delay Refresh")
110
111
112 class DATA_PT_bone_groups(DataButtonsPanel, bpy.types.Panel):
113     bl_label = "Bone Groups"
114
115     @staticmethod
116     def poll(context):
117         return (context.object and context.object.type == 'ARMATURE' and context.object.pose)
118
119     def draw(self, context):
120         layout = self.layout
121
122         ob = context.object
123         pose = ob.pose
124
125         row = layout.row()
126         row.template_list(pose, "bone_groups", pose, "active_bone_group_index", rows=2)
127
128         col = row.column(align=True)
129         col.active = (ob.proxy is None)
130         col.operator("pose.group_add", icon='ZOOMIN', text="")
131         col.operator("pose.group_remove", icon='ZOOMOUT', text="")
132
133         group = pose.active_bone_group
134         if group:
135             col = layout.column()
136             col.active = (ob.proxy is None)
137             col.prop(group, "name")
138
139             split = layout.split()
140             split.active = (ob.proxy is None)
141
142             col = split.column()
143             col.prop(group, "color_set")
144             if group.color_set:
145                 col = split.column()
146                 col.template_triColorSet(group, "colors")
147
148         row = layout.row()
149         row.active = (ob.proxy is None)
150
151         sub = row.row(align=True)
152         sub.operator("pose.group_assign", text="Assign")
153         sub.operator("pose.group_unassign", text="Remove") #row.operator("pose.bone_group_remove_from", text="Remove")
154
155         sub = row.row(align=True)
156         sub.operator("pose.group_select", text="Select")
157         sub.operator("pose.group_deselect", text="Deselect")
158
159
160 # TODO: this panel will soon be depreceated too
161 class DATA_PT_ghost(DataButtonsPanel, bpy.types.Panel):
162     bl_label = "Ghost"
163
164     def draw(self, context):
165         layout = self.layout
166
167         arm = context.armature
168
169         layout.prop(arm, "ghost_type", expand=True)
170
171         split = layout.split()
172
173         col = split.column()
174
175         sub = col.column(align=True)
176         if arm.ghost_type == 'RANGE':
177             sub.prop(arm, "ghost_frame_start", text="Start")
178             sub.prop(arm, "ghost_frame_end", text="End")
179             sub.prop(arm, "ghost_size", text="Step")
180         elif arm.ghost_type == 'CURRENT_FRAME':
181             sub.prop(arm, "ghost_step", text="Range")
182             sub.prop(arm, "ghost_size", text="Step")
183
184         col = split.column()
185         col.label(text="Display:")
186         col.prop(arm, "ghost_only_selected", text="Selected Only")
187
188
189 class DATA_PT_iksolver_itasc(DataButtonsPanel, bpy.types.Panel):
190     bl_label = "iTaSC parameters"
191     bl_default_closed = True
192
193     @staticmethod
194     def poll(context):
195         ob = context.object
196         return (ob and ob.pose)
197
198     def draw(self, context):
199         layout = self.layout
200
201         ob = context.object
202
203         itasc = ob.pose.ik_param
204
205         row = layout.row()
206         row.prop(ob.pose, "ik_solver")
207
208         if itasc:
209             layout.prop(itasc, "mode", expand=True)
210             simulation = (itasc.mode == 'SIMULATION')
211             if simulation:
212                 layout.label(text="Reiteration:")
213                 layout.prop(itasc, "reiteration", expand=True)
214
215             split = layout.split()
216             split.active = not simulation or itasc.reiteration != 'NEVER'
217             col = split.column()
218             col.prop(itasc, "precision")
219
220             col = split.column()
221             col.prop(itasc, "num_iter")
222
223
224             if simulation:
225                 layout.prop(itasc, "auto_step")
226                 row = layout.row()
227                 if itasc.auto_step:
228                     row.prop(itasc, "min_step", text="Min")
229                     row.prop(itasc, "max_step", text="Max")
230                 else:
231                     row.prop(itasc, "num_step")
232
233             layout.prop(itasc, "solver")
234             if simulation:
235                 layout.prop(itasc, "feedback")
236                 layout.prop(itasc, "max_velocity")
237             if itasc.solver == 'DLS':
238                 row = layout.row()
239                 row.prop(itasc, "dampmax", text="Damp", slider=True)
240                 row.prop(itasc, "dampeps", text="Eps", slider=True)
241
242 from properties_animviz import MotionPathButtonsPanel, OnionSkinButtonsPanel
243
244 class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
245     #bl_label = "Bones Motion Paths"
246     bl_context = "data"
247
248     @staticmethod
249     def poll(context):
250         # XXX: include posemode check?
251         return (context.object) and (context.armature)
252
253     def draw(self, context):
254         layout = self.layout
255
256         ob = context.object
257
258         self.draw_settings(context, ob.pose.animation_visualisation, bones=True)
259
260         layout.separator()
261
262         split = layout.split()
263
264         col = split.column()
265         col.operator("pose.paths_calculate", text="Calculate Paths")
266
267         col = split.column()
268         col.operator("pose.paths_clear", text="Clear Paths")
269
270
271 class DATA_PT_onion_skinning(OnionSkinButtonsPanel): #, bpy.types.Panel): # inherit from panel when ready
272     #bl_label = "Bones Onion Skinning"
273     bl_context = "data"
274
275     @staticmethod
276     def poll(context):
277         # XXX: include posemode check?
278         return (context.object) and (context.armature)
279
280     def draw(self, context):
281         layout = self.layout
282
283         ob = context.object
284
285         self.draw_settings(context, ob.pose.animation_visualisation, bones=True)
286
287 def register():
288     pass
289
290
291 def unregister():
292     pass
293
294 if __name__ == "__main__":
295     register()