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