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