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