fix [#26754] Live Edit and Editing UI scripts don't work
[blender.git] / release / scripts / startup / bl_ui / properties_scene.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 SceneButtonsPanel():
25     bl_space_type = 'PROPERTIES'
26     bl_region_type = 'WINDOW'
27     bl_context = "scene"
28
29     @classmethod
30     def poll(cls, context):
31         return context.scene
32
33
34 class SCENE_PT_scene(SceneButtonsPanel, bpy.types.Panel):
35     bl_label = "Scene"
36     COMPAT_ENGINES = {'BLENDER_RENDER'}
37
38     def draw(self, context):
39         layout = self.layout
40         scene = context.scene
41
42         layout.prop(scene, "camera")
43         layout.prop(scene, "background_set", text="Background")
44
45
46 class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel):
47     bl_label = "Units"
48     COMPAT_ENGINES = {'BLENDER_RENDER'}
49
50     def draw(self, context):
51         layout = self.layout
52         unit = context.scene.unit_settings
53
54         col = layout.column()
55         col.row().prop(unit, "system", expand=True)
56         col.row().prop(unit, "system_rotation", expand=True)
57
58         row = layout.row()
59         row.active = (unit.system != 'NONE')
60         row.prop(unit, "scale_length", text="Scale")
61         row.prop(unit, "use_separate")
62
63
64 class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel):
65     bl_label = "Keying Sets"
66
67     def draw(self, context):
68         layout = self.layout
69
70         scene = context.scene
71         row = layout.row()
72
73         col = row.column()
74         col.template_list(scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
75
76         col = row.column(align=True)
77         col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
78         col.operator("anim.keying_set_remove", icon='ZOOMOUT', text="")
79
80         ks = scene.keying_sets.active
81         if ks and ks.is_path_absolute:
82             row = layout.row()
83
84             col = row.column()
85             col.prop(ks, "name")
86
87             subcol = col.column()
88             subcol.operator_context = 'INVOKE_DEFAULT'
89             op = subcol.operator("anim.keying_set_export", text="Export to File")
90             op.filepath = "keyingset.py"
91
92             col = row.column()
93             col.label(text="Keyframing Settings:")
94             col.prop(ks, "bl_options")
95
96
97 class SCENE_PT_keying_set_paths(SceneButtonsPanel, bpy.types.Panel):
98     bl_label = "Active Keying Set"
99
100     @classmethod
101     def poll(cls, context):
102         ks = context.scene.keying_sets.active
103         return (ks and ks.is_path_absolute)
104
105     def draw(self, context):
106         layout = self.layout
107
108         scene = context.scene
109         ks = scene.keying_sets.active
110
111         row = layout.row()
112         row.label(text="Paths:")
113
114         row = layout.row()
115
116         col = row.column()
117         col.template_list(ks, "paths", ks.paths, "active_index", rows=2)
118
119         col = row.column(align=True)
120         col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
121         col.operator("anim.keying_set_path_remove", icon='ZOOMOUT', text="")
122
123         ksp = ks.paths.active
124         if ksp:
125             col = layout.column()
126             col.label(text="Target:")
127             col.template_any_ID(ksp, "id", "id_type")
128             col.template_path_builder(ksp, "data_path", ksp.id)
129
130             row = layout.row()
131
132             col = row.column()
133             col.label(text="Array Target:")
134             col.prop(ksp, "use_entire_array")
135             if ksp.use_entire_array is False:
136                 col.prop(ksp, "array_index")
137
138             col = row.column()
139             col.label(text="F-Curve Grouping:")
140             col.prop(ksp, "group_method")
141             if ksp.group_method == 'NAMED':
142                 col.prop(ksp, "group")
143
144             col.prop(ksp, "bl_options")
145
146
147 class SCENE_PT_physics(SceneButtonsPanel, bpy.types.Panel):
148     bl_label = "Gravity"
149     COMPAT_ENGINES = {'BLENDER_RENDER'}
150
151     def draw_header(self, context):
152         self.layout.prop(context.scene, "use_gravity", text="")
153
154     def draw(self, context):
155         layout = self.layout
156
157         scene = context.scene
158
159         layout.active = scene.use_gravity
160
161         layout.prop(scene, "gravity", text="")
162
163
164 class SCENE_PT_simplify(SceneButtonsPanel, bpy.types.Panel):
165     bl_label = "Simplify"
166     COMPAT_ENGINES = {'BLENDER_RENDER'}
167
168     def draw_header(self, context):
169         scene = context.scene
170         rd = scene.render
171         self.layout.prop(rd, "use_simplify", text="")
172
173     def draw(self, context):
174         layout = self.layout
175         scene = context.scene
176         rd = scene.render
177
178         layout.active = rd.use_simplify
179
180         split = layout.split()
181
182         col = split.column()
183         col.prop(rd, "simplify_subdivision", text="Subdivision")
184         col.prop(rd, "simplify_child_particles", text="Child Particles")
185
186         col.prop(rd, "use_simplify_triangulate")
187
188         col = split.column()
189         col.prop(rd, "simplify_shadow_samples", text="Shadow Samples")
190         col.prop(rd, "simplify_ao_sss", text="AO and SSS")
191
192
193 class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, bpy.types.Panel):
194     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
195     _context_path = "scene"
196     _property_type = bpy.types.Scene
197
198 #  XXX, move operator to op/ dir
199
200
201 class ANIM_OT_keying_set_export(bpy.types.Operator):
202     "Export Keying Set to a python script."
203     bl_idname = "anim.keying_set_export"
204     bl_label = "Export Keying Set..."
205
206     filepath = bpy.props.StringProperty(name="File Path", description="Filepath to write file to.")
207     filter_folder = bpy.props.BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'})
208     filter_text = bpy.props.BoolProperty(name="Filter text", description="", default=True, options={'HIDDEN'})
209     filter_python = bpy.props.BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'})
210
211     def execute(self, context):
212         if not self.filepath:
213             raise Exception("Filepath not set.")
214
215         f = open(self.filepath, "w")
216         if not f:
217             raise Exception("Could not open file.")
218
219         scene = context.scene
220         ks = scene.keying_sets.active
221
222         f.write("# Keying Set: %s\n" % ks.name)
223
224         f.write("import bpy\n\n")
225         f.write("scene= bpy.data.scenes[0]\n\n")  # XXX, why not use the current scene?
226
227         # Add KeyingSet and set general settings
228         f.write("# Keying Set Level declarations\n")
229         f.write("ks= scene.keying_sets.new(name=\"%s\")\n" % ks.name)
230
231         if not ks.is_path_absolute:
232             f.write("ks.is_path_absolute = False\n")
233         f.write("\n")
234
235         f.write("ks.bl_options = %r\n" % ks.bl_options)
236         f.write("\n")
237
238         # generate and write set of lookups for id's used in paths
239         id_to_paths_cache = {}  # cache for syncing ID-blocks to bpy paths + shorthands
240
241         for ksp in ks.paths:
242             if ksp.id is None:
243                 continue
244             if ksp.id in id_to_paths_cache:
245                 continue
246
247             # - idtype_list is used to get the list of id-datablocks from bpy.data.*
248             #   since this info isn't available elsewhere
249             # - id.bl_rna.name gives a name suitable for UI,
250             #   with a capitalised first letter, but we need
251             #   the plural form that's all lower case
252             idtype_list = ksp.id.bl_rna.name.lower() + "s"
253             id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, ksp.id.name)
254
255             # shorthand ID for the ID-block (as used in the script)
256             short_id = "id_%d" % len(id_to_paths_cache)
257
258             # store this in the cache now
259             id_to_paths_cache[ksp.id] = [short_id, id_bpy_path]
260
261         f.write("# ID's that are commonly used\n")
262         for id_pair in id_to_paths_cache.values():
263             f.write("%s = %s\n" % (id_pair[0], id_pair[1]))
264         f.write("\n")
265
266         # write paths
267         f.write("# Path Definitions\n")
268         for ksp in ks.paths:
269             f.write("ksp = ks.paths.add(")
270
271             # id-block + data_path
272             if ksp.id:
273                 # find the relevant shorthand from the cache
274                 id_bpy_path = id_to_paths_cache[ksp.id][0]
275             else:
276                 id_bpy_path = "None"  # XXX...
277             f.write("%s, '%s'" % (id_bpy_path, ksp.data_path))
278
279             # array index settings (if applicable)
280             if ksp.use_entire_array:
281                 f.write(", index=-1")
282             else:
283                 f.write(", index=%d" % ksp.array_index)
284
285             # grouping settings (if applicable)
286             # NOTE: the current default is KEYINGSET, but if this changes, change this code too
287             if ksp.group_method == 'NAMED':
288                 f.write(", group_method='%s', group_name=\"%s\"" % (ksp.group_method, ksp.group))
289             elif ksp.group_method != 'KEYINGSET':
290                 f.write(", group_method='%s'" % ksp.group_method)
291
292             # finish off
293             f.write(")\n")
294
295         f.write("\n")
296         f.close()
297
298         return {'FINISHED'}
299
300     def invoke(self, context, event):
301         wm = context.window_manager
302         wm.fileselect_add(self)
303         return {'RUNNING_MODAL'}
304
305 if __name__ == "__main__":  # only for live edit.
306     bpy.utils.register_module(__name__)