1
# ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17
# ##### END GPL LICENSE BLOCK #####
23
if "anim_utils" in locals():
24
imp.reload(anim_utils)
27
from bpy.types import Operator
28
from bpy.props import (IntProperty,
35
class ANIM_OT_keying_set_export(Operator):
36
"Export Keying Set to a python script"
37
bl_idname = "anim.keying_set_export"
38
bl_label = "Export Keying Set..."
40
filepath = StringProperty(
43
filter_folder = BoolProperty(
44
name="Filter folders",
48
filter_text = BoolProperty(
53
filter_python = BoolProperty(
59
def execute(self, context):
61
raise Exception("Filepath not set")
63
f = open(self.filepath, "w")
65
raise Exception("Could not open file")
68
ks = scene.keying_sets.active
70
f.write("# Keying Set: %s\n" % ks.bl_idname)
72
f.write("import bpy\n\n")
73
f.write("scene = bpy.context.scene\n\n")
75
# Add KeyingSet and set general settings
76
f.write("# Keying Set Level declarations\n")
77
f.write("ks = scene.keying_sets.new(idname=\"%s\", name=\"%s\")\n"
78
"" % (ks.bl_idname, ks.bl_label))
79
f.write("ks.bl_description = \"%s\"\n" % ks.bl_description)
81
if not ks.is_path_absolute:
82
f.write("ks.is_path_absolute = False\n")
85
f.write("ks.bl_options = %r\n" % ks.bl_options)
88
# --------------------------------------------------------
89
# generate and write set of lookups for id's used in paths
91
# cache for syncing ID-blocks to bpy paths + shorthand's
92
id_to_paths_cache = {}
97
if ksp.id in id_to_paths_cache:
101
- idtype_list is used to get the list of id-datablocks from
102
bpy.data.* since this info isn't available elsewhere
103
- id.bl_rna.name gives a name suitable for UI,
104
with a capitalised first letter, but we need
105
the plural form that's all lower case
108
idtype_list = ksp.id.bl_rna.name.lower() + "s"
109
id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, ksp.id.name)
111
# shorthand ID for the ID-block (as used in the script)
112
short_id = "id_%d" % len(id_to_paths_cache)
114
# store this in the cache now
115
id_to_paths_cache[ksp.id] = [short_id, id_bpy_path]
117
f.write("# ID's that are commonly used\n")
118
for id_pair in id_to_paths_cache.values():
119
f.write("%s = %s\n" % (id_pair[0], id_pair[1]))
123
f.write("# Path Definitions\n")
125
f.write("ksp = ks.paths.add(")
127
# id-block + data_path
129
# find the relevant shorthand from the cache
130
id_bpy_path = id_to_paths_cache[ksp.id][0]
132
id_bpy_path = "None" # XXX...
133
f.write("%s, '%s'" % (id_bpy_path, ksp.data_path))
135
# array index settings (if applicable)
136
if ksp.use_entire_array:
137
f.write(", index=-1")
139
f.write(", index=%d" % ksp.array_index)
141
# grouping settings (if applicable)
142
# NOTE: the current default is KEYINGSET, but if this changes,
143
# change this code too
144
if ksp.group_method == 'NAMED':
145
f.write(", group_method='%s', group_name=\"%s\"" %
146
(ksp.group_method, ksp.group))
147
elif ksp.group_method != 'KEYINGSET':
148
f.write(", group_method='%s'" % ksp.group_method)
158
def invoke(self, context, event):
159
wm = context.window_manager
160
wm.fileselect_add(self)
161
return {'RUNNING_MODAL'}
164
class BakeAction(Operator):
165
"""Bake object/pose loc/scale/rotation animation to a new action"""
166
bl_idname = "nla.bake"
167
bl_label = "Bake Action"
168
bl_options = {'REGISTER', 'UNDO'}
170
frame_start = IntProperty(
172
description="Start frame for baking",
176
frame_end = IntProperty(
178
description="End frame for baking",
184
description="Frame Step",
188
only_selected = BoolProperty(
189
name="Only Selected",
192
clear_consraints = BoolProperty(
193
name="Clear Constraints",
196
bake_types = EnumProperty(
198
options={'ENUM_FLAG'},
199
items=(('POSE', "Pose", ""),
200
('OBJECT', "Object", ""),
205
def execute(self, context):
207
from bpy_extras import anim_utils
209
action = anim_utils.bake_action(self.frame_start,
213
'POSE' in self.bake_types,
214
'OBJECT' in self.bake_types,
215
self.clear_consraints,
220
self.report({'INFO'}, "Nothing to bake")
225
def invoke(self, context, event):
226
wm = context.window_manager
227
return wm.invoke_props_dialog(self)
230
class ClearUselessActions(Operator):
231
"""Mark actions with no F-Curves for deletion after save & reload of """ \
232
"""file preserving \"action libraries\""""
233
bl_idname = "anim.clear_useless_actions"
234
bl_label = "Clear Useless Actions"
235
bl_options = {'REGISTER', 'UNDO'}
237
only_unused = BoolProperty(name="Only Unused",
238
description="Only unused (Fake User only) actions get considered",
242
def poll(cls, context):
243
return bool(bpy.data.actions)
245
def execute(self, context):
248
for action in bpy.data.actions:
249
# if only user is "fake" user...
250
if ((self.only_unused is False) or
251
(action.use_fake_user and action.users == 1)):
253
# if it has F-Curves, then it's a "action library"
254
# (i.e. walk, wave, jump, etc.)
255
# and should be left alone as that's what fake users are for!
256
if not action.fcurves:
257
# mark action for deletion
261
self.report({'INFO'}, "Removed %d empty and/or fake-user only Actions"
266
class UpdateAnimData(Operator):
267
"""Update data paths from 2.56 and previous versions, """ \
268
"""modifying data paths of drivers and fcurves"""
269
bl_idname = "anim.update_data_paths"
270
bl_label = "Update Animation Data"
272
def execute(self, context):
273
import animsys_refactor
274
animsys_refactor.update_data_paths(animsys_refactor.data_2_56_to_2_59)