4e45b20e76f927616c20b5b5af32b5c6438749ba
[blender.git] / release / scripts / startup / bl_ui / properties_mask_common.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-80 compliant>
20
21 # panels get subclassed (not registered directly)
22 # menus are referenced `as is`
23
24 import bpy
25 from bpy.types import Menu, UIList
26
27
28 class MASK_UL_layers(UIList):
29     def draw_item(self, context, layout, data, item, icon,
30                   active_data, active_propname, index):
31         # assert(isinstance(item, bpy.types.MaskLayer)
32         mask = item
33         if self.layout_type in {'DEFAULT', 'COMPACT'}:
34             layout.label(text=mask.name, translate=False, icon_value=icon)
35             row = layout.row(align=True)
36             row.prop(mask, "hide", text="", emboss=False)
37             row.prop(mask, "hide_select", text="", emboss=False)
38             row.prop(mask, "hide_render", text="", emboss=False)
39         elif self.layout_type in {'GRID'}:
40             layout.alignment = 'CENTER'
41             layout.label(text="", icon_value=icon)
42
43
44 class MASK_PT_mask:
45     # subclasses must define...
46     #~ bl_space_type = 'CLIP_EDITOR'
47     #~ bl_region_type = 'UI'
48     bl_label = "Mask Settings"
49     bl_options = {'DEFAULT_CLOSED'}
50
51     @classmethod
52     def poll(cls, context):
53         space_data = context.space_data
54         return space_data.mask and space_data.mode == 'MASK'
55
56     def draw(self, context):
57         layout = self.layout
58
59         sc = context.space_data
60         mask = sc.mask
61
62         col = layout.column(align=True)
63         col.prop(mask, "frame_start")
64         col.prop(mask, "frame_end")
65
66
67 class MASK_PT_layers:
68     # subclasses must define...
69     #~ bl_space_type = 'CLIP_EDITOR'
70     #~ bl_region_type = 'UI'
71     bl_label = "Mask Layers"
72
73     @classmethod
74     def poll(cls, context):
75         space_data = context.space_data
76         return space_data.mask and space_data.mode == 'MASK'
77
78     def draw(self, context):
79         layout = self.layout
80
81         sc = context.space_data
82         mask = sc.mask
83         active_layer = mask.layers.active
84
85         rows = 5 if active_layer else 2
86
87         row = layout.row()
88         row.template_list("MASK_UL_layers", "", mask, "layers",
89                           mask, "active_layer_index", rows=rows)
90
91         sub = row.column(align=True)
92
93         sub.operator("mask.layer_new", icon='ZOOMIN', text="")
94         sub.operator("mask.layer_remove", icon='ZOOMOUT', text="")
95
96         if active_layer:
97             sub.separator()
98
99             props = sub.operator("mask.layer_move", icon='TRIA_UP', text="")
100             props.direction = 'UP'
101
102             props = sub.operator("mask.layer_move", icon='TRIA_DOWN', text="")
103             props.direction = 'DOWN'
104
105             layout.prop(active_layer, "name")
106
107             # blending
108             row = layout.row(align=True)
109             row.prop(active_layer, "alpha")
110             row.prop(active_layer, "invert", text="", icon='IMAGE_ALPHA')
111
112             layout.prop(active_layer, "blend")
113             layout.prop(active_layer, "falloff")
114
115
116 class MASK_PT_spline():
117     # subclasses must define...
118     #~ bl_space_type = 'CLIP_EDITOR'
119     #~ bl_region_type = 'UI'
120     bl_label = "Active Spline"
121
122     @classmethod
123     def poll(cls, context):
124         sc = context.space_data
125         mask = sc.mask
126
127         if mask and sc.mode == 'MASK':
128             return mask.layers.active and mask.layers.active.splines.active
129
130         return False
131
132     def draw(self, context):
133         layout = self.layout
134
135         sc = context.space_data
136         mask = sc.mask
137         spline = mask.layers.active.splines.active
138
139         col = layout.column()
140         col.prop(spline, "offset_mode")
141         col.prop(spline, "weight_interpolation")
142
143         row = col.row()
144         row.prop(spline, "use_cyclic")
145         row.prop(spline, "use_fill")
146
147         col.prop(spline, "use_self_intersection_check")
148
149
150 class MASK_PT_point():
151     # subclasses must define...
152     #~ bl_space_type = 'CLIP_EDITOR'
153     #~ bl_region_type = 'UI'
154     bl_label = "Active Point"
155
156     @classmethod
157     def poll(cls, context):
158         sc = context.space_data
159         mask = sc.mask
160
161         if mask and sc.mode == 'MASK':
162             mask_layer_active = mask.layers.active
163             return (mask_layer_active and
164                     mask_layer_active.splines.active_point)
165
166         return False
167
168     def draw(self, context):
169         layout = self.layout
170
171         sc = context.space_data
172         mask = sc.mask
173         point = mask.layers.active.splines.active_point
174         parent = point.parent
175
176         col = layout.column()
177         col.prop(point, "handle_type")
178
179         col = layout.column()
180         # Currently only parenting yo movie clip is allowed, so do not
181         # ver-oplicate things for now and use single template_ID
182         #col.template_any_ID(parent, "id", "id_type", text="")
183
184         col.label("Parent:")
185         col.prop(parent, "id", text="")
186
187         if parent.id_type == 'MOVIECLIP' and parent.id:
188             clip = parent.id
189             tracking = clip.tracking
190
191             row = col.row()
192             row.prop(parent, "type", expand=True)
193
194             col.prop_search(parent, "parent", tracking,
195                             "objects", icon='OBJECT_DATA', text="Object:")
196
197             tracks_list = "tracks" if parent.type == 'POINT_TRACK' else 'plane_tracks'
198
199             if parent.parent in tracking.objects:
200                 object = tracking.objects[parent.parent]
201                 col.prop_search(parent, "sub_parent", object,
202                                 tracks_list, icon='ANIM_DATA', text="Track:")
203             else:
204                 col.prop_search(parent, "sub_parent", tracking,
205                                 tracks_list, icon='ANIM_DATA', text="Track:")
206
207
208 class MASK_PT_display():
209     # subclasses must define...
210     #~ bl_space_type = 'CLIP_EDITOR'
211     #~ bl_region_type = 'UI'
212     bl_label = "Mask Display"
213     bl_options = {'DEFAULT_CLOSED'}
214
215     @classmethod
216     def poll(cls, context):
217         space_data = context.space_data
218         return space_data.mask and space_data.mode == 'MASK'
219
220     def draw(self, context):
221         layout = self.layout
222
223         space_data = context.space_data
224
225         layout.prop(space_data, "mask_draw_type", text="")
226         layout.prop(space_data, "show_mask_smooth")
227
228
229 class MASK_PT_tools():
230     # subclasses must define...
231     #~ bl_space_type = 'CLIP_EDITOR'
232     #~ bl_region_type = 'TOOLS'
233     bl_label = "Mask Tools"
234
235     @classmethod
236     def poll(cls, context):
237         space_data = context.space_data
238         return space_data.mask and space_data.mode == 'MASK'
239
240     def draw(self, context):
241         layout = self.layout
242
243         col = layout.column(align=True)
244         col.label(text="Transform:")
245         col.operator("transform.translate")
246         col.operator("transform.rotate")
247         col.operator("transform.resize", text="Scale")
248         props = col.operator("transform.transform", text="Scale Feather")
249         props.mode = 'MASK_SHRINKFATTEN'
250
251         col = layout.column(align=True)
252         col.label(text="Spline:")
253         col.operator("mask.delete")
254         col.operator("mask.cyclic_toggle")
255         col.operator("mask.switch_direction")
256         col.operator("mask.handle_type_set")
257
258         col = layout.column(align=True)
259         col.label(text="Parenting:")
260         col.operator("mask.parent_set")
261         col.operator("mask.parent_clear")
262
263         col = layout.column(align=True)
264         col.label(text="Animation:")
265         col.operator("mask.shape_key_clear")
266         col.operator("mask.shape_key_insert")
267         col.operator("mask.shape_key_feather_reset")
268         col.operator("mask.shape_key_rekey")
269
270
271 class MASK_MT_mask(Menu):
272     bl_label = "Mask"
273
274     def draw(self, context):
275         layout = self.layout
276
277         layout.operator("mask.delete")
278
279         layout.separator()
280         layout.operator("mask.cyclic_toggle")
281         layout.operator("mask.switch_direction")
282         layout.operator("mask.normals_make_consistent")
283         layout.operator("mask.feather_weight_clear")  # TODO, better place?
284
285         layout.separator()
286         layout.operator("mask.parent_clear")
287         layout.operator("mask.parent_set")
288
289         layout.separator()
290         layout.menu("MASK_MT_visibility")
291         layout.menu("MASK_MT_transform")
292         layout.menu("MASK_MT_animation")
293
294
295 class MASK_MT_visibility(Menu):
296     bl_label = "Show/Hide"
297
298     def draw(self, context):
299         layout = self.layout
300
301         layout.operator("mask.hide_view_clear", text="Show Hidden")
302         layout.operator("mask.hide_view_set", text="Hide Selected")
303
304         props = layout.operator("mask.hide_view_set", text="Hide Unselected")
305         props.unselected = True
306
307
308 class MASK_MT_transform(Menu):
309     bl_label = "Transform"
310
311     def draw(self, context):
312         layout = self.layout
313
314         layout.operator("transform.translate")
315         layout.operator("transform.rotate")
316         layout.operator("transform.resize")
317         props = layout.operator("transform.transform", text="Scale Feather")
318         props.mode = 'MASK_SHRINKFATTEN'
319
320
321 class MASK_MT_animation(Menu):
322     bl_label = "Animation"
323
324     def draw(self, context):
325         layout = self.layout
326
327         layout.operator("mask.shape_key_clear")
328         layout.operator("mask.shape_key_insert")
329         layout.operator("mask.shape_key_feather_reset")
330         layout.operator("mask.shape_key_rekey")
331
332
333 class MASK_MT_select(Menu):
334     bl_label = "Select"
335
336     def draw(self, context):
337         layout = self.layout
338         sc = context.space_data
339
340         layout.operator("mask.select_border")
341         layout.operator("mask.select_circle")
342
343         layout.separator()
344
345         layout.operator("mask.select_more")
346         layout.operator("mask.select_less")
347
348         layout.separator()
349
350         layout.operator("mask.select_all").action = 'TOGGLE'
351         layout.operator("mask.select_all", text="Inverse").action = 'INVERT'
352
353 if __name__ == "__main__":  # only for live edit.
354     bpy.utils.register_module(__name__)