| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | # ##### BEGIN GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | #  modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | #  as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | #  of the License, or (at your option) any later version. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | #  GNU General Public License for more details. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | #  along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  | #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ##### END GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # <pep8-80 compliant> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | if "bpy" in locals(): | 
					
						
							| 
									
										
										
										
											2015-01-23 12:37:58 +11:00
										 |  |  |     from importlib import reload | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |     if "anim_utils" in locals(): | 
					
						
							| 
									
										
										
										
											2015-01-23 12:37:58 +11:00
										 |  |  |         reload(anim_utils) | 
					
						
							|  |  |  |     del reload | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | import bpy | 
					
						
							|  |  |  | from bpy.types import Operator | 
					
						
							| 
									
										
										
										
											2015-01-27 17:46:07 +11:00
										 |  |  | from bpy.props import ( | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |     IntProperty, | 
					
						
							|  |  |  |     BoolProperty, | 
					
						
							|  |  |  |     EnumProperty, | 
					
						
							|  |  |  |     StringProperty, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ANIM_OT_keying_set_export(Operator): | 
					
						
							| 
									
										
										
										
											2017-04-14 20:01:43 +10:00
										 |  |  |     """Export Keying Set to a python script""" | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  |     bl_idname = "anim.keying_set_export" | 
					
						
							|  |  |  |     bl_label = "Export Keying Set..." | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |     filepath = StringProperty( | 
					
						
							| 
									
										
										
										
											2011-12-11 21:23:29 +00:00
										 |  |  |             subtype='FILE_PATH', | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |             ) | 
					
						
							|  |  |  |     filter_folder = BoolProperty( | 
					
						
							|  |  |  |             name="Filter folders", | 
					
						
							|  |  |  |             default=True, | 
					
						
							|  |  |  |             options={'HIDDEN'}, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |     filter_text = BoolProperty( | 
					
						
							|  |  |  |             name="Filter text", | 
					
						
							|  |  |  |             default=True, | 
					
						
							|  |  |  |             options={'HIDDEN'}, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |     filter_python = BoolProperty( | 
					
						
							|  |  |  |             name="Filter python", | 
					
						
							|  |  |  |             default=True, | 
					
						
							|  |  |  |             options={'HIDDEN'}, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def execute(self, context): | 
					
						
							|  |  |  |         if not self.filepath: | 
					
						
							|  |  |  |             raise Exception("Filepath not set") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f = open(self.filepath, "w") | 
					
						
							|  |  |  |         if not f: | 
					
						
							|  |  |  |             raise Exception("Could not open file") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         scene = context.scene | 
					
						
							|  |  |  |         ks = scene.keying_sets.active | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-08 14:04:06 +00:00
										 |  |  |         f.write("# Keying Set: %s\n" % ks.bl_idname) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         f.write("import bpy\n\n") | 
					
						
							| 
									
										
										
										
											2012-03-08 14:04:06 +00:00
										 |  |  |         f.write("scene = bpy.context.scene\n\n") | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # Add KeyingSet and set general settings | 
					
						
							|  |  |  |         f.write("# Keying Set Level declarations\n") | 
					
						
							| 
									
										
										
										
											2012-03-08 14:04:06 +00:00
										 |  |  |         f.write("ks = scene.keying_sets.new(idname=\"%s\", name=\"%s\")\n" | 
					
						
							|  |  |  |                 "" % (ks.bl_idname, ks.bl_label)) | 
					
						
							|  |  |  |         f.write("ks.bl_description = \"%s\"\n" % ks.bl_description) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if not ks.is_path_absolute: | 
					
						
							|  |  |  |             f.write("ks.is_path_absolute = False\n") | 
					
						
							|  |  |  |         f.write("\n") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-26 19:15:46 +13:00
										 |  |  |         f.write("ks.use_insertkey_needed = %s\n" % ks.use_insertkey_needed) | 
					
						
							|  |  |  |         f.write("ks.use_insertkey_visual = %s\n" % ks.use_insertkey_visual) | 
					
						
							|  |  |  |         f.write("ks.use_insertkey_xyz_to_rgb = %s\n" % ks.use_insertkey_xyz_to_rgb) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  |         f.write("\n") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |         # -------------------------------------------------------- | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  |         # generate and write set of lookups for id's used in paths | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-17 06:58:07 +00:00
										 |  |  |         # cache for syncing ID-blocks to bpy paths + shorthand's | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |         id_to_paths_cache = {} | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for ksp in ks.paths: | 
					
						
							|  |  |  |             if ksp.id is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if ksp.id in id_to_paths_cache: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-14 20:01:43 +10:00
										 |  |  |             # - idtype_list is used to get the list of id-datablocks from | 
					
						
							|  |  |  |             #   bpy.data.* since this info isn't available elsewhere | 
					
						
							|  |  |  |             # - id.bl_rna.name gives a name suitable for UI, | 
					
						
							|  |  |  |             #   with a capitalised first letter, but we need | 
					
						
							|  |  |  |             #   the plural form that's all lower case | 
					
						
							|  |  |  |             # - special handling is needed for "nested" ID-blocks | 
					
						
							|  |  |  |             #   (e.g. nodetree in Material) | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |             if ksp.id.bl_rna.identifier.startswith("ShaderNodeTree"): | 
					
						
							|  |  |  |                 # Find material or lamp using this node tree... | 
					
						
							|  |  |  |                 id_bpy_path = "bpy.data.nodes[\"%s\"]" | 
					
						
							|  |  |  |                 found = False | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |                 for mat in bpy.data.materials: | 
					
						
							|  |  |  |                     if mat.node_tree == ksp.id: | 
					
						
							|  |  |  |                         id_bpy_path = "bpy.data.materials[\"%s\"].node_tree" % (mat.name) | 
					
						
							|  |  |  |                         found = True | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                         break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |                 if not found: | 
					
						
							|  |  |  |                     for lamp in bpy.data.lamps: | 
					
						
							|  |  |  |                         if lamp.node_tree == ksp.id: | 
					
						
							|  |  |  |                             id_bpy_path = "bpy.data.lamps[\"%s\"].node_tree" % (lamp.name) | 
					
						
							|  |  |  |                             found = True | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                             break | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |                 if not found: | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                     self.report({'WARN'}, "Could not find material or lamp using Shader Node Tree - %s" % (ksp.id)) | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |             elif ksp.id.bl_rna.identifier.startswith("CompositorNodeTree"): | 
					
						
							|  |  |  |                 # Find compositor nodetree using this node tree... | 
					
						
							|  |  |  |                 for scene in bpy.data.scenes: | 
					
						
							|  |  |  |                     if scene.node_tree == ksp.id: | 
					
						
							|  |  |  |                         id_bpy_path = "bpy.data.scenes[\"%s\"].node_tree" % (scene.name) | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                         break | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                     self.report({'WARN'}, "Could not find scene using Compositor Node Tree - %s" % (ksp.id)) | 
					
						
							| 
									
										
										
										
											2017-08-18 01:03:28 +12:00
										 |  |  |             elif ksp.id.bl_rna.name == "Key": | 
					
						
							|  |  |  |                 # "keys" conflicts with a Python keyword, hence the simple solution won't work | 
					
						
							|  |  |  |                 id_bpy_path = "bpy.data.shape_keys[\"%s\"]" % (ksp.id.name) | 
					
						
							| 
									
										
										
										
											2016-02-20 17:53:32 +13:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 idtype_list = ksp.id.bl_rna.name.lower() + "s" | 
					
						
							|  |  |  |                 id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, ksp.id.name) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # shorthand ID for the ID-block (as used in the script) | 
					
						
							|  |  |  |             short_id = "id_%d" % len(id_to_paths_cache) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # store this in the cache now | 
					
						
							|  |  |  |             id_to_paths_cache[ksp.id] = [short_id, id_bpy_path] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.write("# ID's that are commonly used\n") | 
					
						
							|  |  |  |         for id_pair in id_to_paths_cache.values(): | 
					
						
							|  |  |  |             f.write("%s = %s\n" % (id_pair[0], id_pair[1])) | 
					
						
							|  |  |  |         f.write("\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # write paths | 
					
						
							|  |  |  |         f.write("# Path Definitions\n") | 
					
						
							|  |  |  |         for ksp in ks.paths: | 
					
						
							|  |  |  |             f.write("ksp = ks.paths.add(") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # id-block + data_path | 
					
						
							|  |  |  |             if ksp.id: | 
					
						
							|  |  |  |                 # find the relevant shorthand from the cache | 
					
						
							|  |  |  |                 id_bpy_path = id_to_paths_cache[ksp.id][0] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 id_bpy_path = "None"  # XXX... | 
					
						
							|  |  |  |             f.write("%s, '%s'" % (id_bpy_path, ksp.data_path)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # array index settings (if applicable) | 
					
						
							|  |  |  |             if ksp.use_entire_array: | 
					
						
							|  |  |  |                 f.write(", index=-1") | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 f.write(", index=%d" % ksp.array_index) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # grouping settings (if applicable) | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |             # NOTE: the current default is KEYINGSET, but if this changes, | 
					
						
							|  |  |  |             # change this code too | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  |             if ksp.group_method == 'NAMED': | 
					
						
							| 
									
										
										
										
											2011-09-23 17:38:52 +00:00
										 |  |  |                 f.write(", group_method='%s', group_name=\"%s\"" % | 
					
						
							|  |  |  |                         (ksp.group_method, ksp.group)) | 
					
						
							| 
									
										
										
										
											2011-09-22 19:50:41 +00:00
										 |  |  |             elif ksp.group_method != 'KEYINGSET': | 
					
						
							|  |  |  |                 f.write(", group_method='%s'" % ksp.group_method) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             # finish off | 
					
						
							|  |  |  |             f.write(")\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.write("\n") | 
					
						
							|  |  |  |         f.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return {'FINISHED'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke(self, context, event): | 
					
						
							|  |  |  |         wm = context.window_manager | 
					
						
							|  |  |  |         wm.fileselect_add(self) | 
					
						
							| 
									
										
										
										
											2011-09-22 20:37:22 +00:00
										 |  |  |         return {'RUNNING_MODAL'} | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BakeAction(Operator): | 
					
						
							| 
									
										
										
										
											2012-02-08 14:01:47 +00:00
										 |  |  |     """Bake object/pose loc/scale/rotation animation to a new action""" | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |     bl_idname = "nla.bake" | 
					
						
							|  |  |  |     bl_label = "Bake Action" | 
					
						
							|  |  |  |     bl_options = {'REGISTER', 'UNDO'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     frame_start = IntProperty( | 
					
						
							|  |  |  |             name="Start Frame", | 
					
						
							|  |  |  |             description="Start frame for baking", | 
					
						
							|  |  |  |             min=0, max=300000, | 
					
						
							|  |  |  |             default=1, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |     frame_end = IntProperty( | 
					
						
							|  |  |  |             name="End Frame", | 
					
						
							|  |  |  |             description="End frame for baking", | 
					
						
							|  |  |  |             min=1, max=300000, | 
					
						
							|  |  |  |             default=250, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |     step = IntProperty( | 
					
						
							|  |  |  |             name="Frame Step", | 
					
						
							|  |  |  |             description="Frame Step", | 
					
						
							|  |  |  |             min=1, max=120, | 
					
						
							|  |  |  |             default=1, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |     only_selected = BoolProperty( | 
					
						
							|  |  |  |             name="Only Selected", | 
					
						
							| 
									
										
										
										
											2016-09-16 11:49:42 +02:00
										 |  |  |             description="Only key selected bones (Pose baking only)", | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |             default=True, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2013-07-04 23:52:02 +00:00
										 |  |  |     visual_keying = BoolProperty( | 
					
						
							|  |  |  |             name="Visual Keying", | 
					
						
							|  |  |  |             description="Keyframe from the final transformations (with constraints applied)", | 
					
						
							|  |  |  |             default=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2012-10-02 13:13:26 +00:00
										 |  |  |     clear_constraints = BoolProperty( | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |             name="Clear Constraints", | 
					
						
							| 
									
										
										
										
											2012-12-28 13:34:19 +00:00
										 |  |  |             description="Remove all constraints from keyed object/bones, and do 'visual' keying", | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |             default=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2013-04-11 08:42:25 +00:00
										 |  |  |     clear_parents = BoolProperty( | 
					
						
							|  |  |  |             name="Clear Parents", | 
					
						
							|  |  |  |             description="Bake animation onto the object then clear parents (objects only)", | 
					
						
							|  |  |  |             default=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2015-05-26 15:30:34 +02:00
										 |  |  |     use_current_action = BoolProperty( | 
					
						
							|  |  |  |             name="Overwrite Current Action", | 
					
						
							|  |  |  |             description="Bake animation into current action, instead of creating a new one " | 
					
						
							|  |  |  |                         "(useful for baking only part of bones in an armature)", | 
					
						
							|  |  |  |             default=False, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |     bake_types = EnumProperty( | 
					
						
							|  |  |  |             name="Bake Data", | 
					
						
							| 
									
										
										
										
											2012-12-28 13:34:19 +00:00
										 |  |  |             description="Which data's transformations to bake", | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |             options={'ENUM_FLAG'}, | 
					
						
							| 
									
										
										
										
											2012-12-28 13:34:19 +00:00
										 |  |  |             items=(('POSE', "Pose", "Bake bones transformations"), | 
					
						
							|  |  |  |                    ('OBJECT', "Object", "Bake object transformations"), | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |                    ), | 
					
						
							|  |  |  |             default={'POSE'}, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def execute(self, context): | 
					
						
							|  |  |  |         from bpy_extras import anim_utils | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-10 14:30:03 +10:00
										 |  |  |         obj = context.object | 
					
						
							| 
									
										
										
										
											2015-05-26 15:30:34 +02:00
										 |  |  |         action = None | 
					
						
							|  |  |  |         if self.use_current_action: | 
					
						
							|  |  |  |             if obj.animation_data: | 
					
						
							|  |  |  |                 action = obj.animation_data.action | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-10 14:30:03 +10:00
										 |  |  |         action = anim_utils.bake_action( | 
					
						
							|  |  |  |             obj, | 
					
						
							|  |  |  |             self.frame_start, | 
					
						
							|  |  |  |             self.frame_end, | 
					
						
							|  |  |  |             frame_step=self.step, | 
					
						
							|  |  |  |             only_selected=self.only_selected, | 
					
						
							|  |  |  |             do_pose='POSE' in self.bake_types, | 
					
						
							|  |  |  |             do_object='OBJECT' in self.bake_types, | 
					
						
							|  |  |  |             do_visual_keying=self.visual_keying, | 
					
						
							|  |  |  |             do_constraint_clear=self.clear_constraints, | 
					
						
							|  |  |  |             do_parents_clear=self.clear_parents, | 
					
						
							|  |  |  |             do_clean=True, | 
					
						
							|  |  |  |             action=action, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if action is None: | 
					
						
							|  |  |  |             self.report({'INFO'}, "Nothing to bake") | 
					
						
							|  |  |  |             return {'CANCELLED'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return {'FINISHED'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def invoke(self, context, event): | 
					
						
							| 
									
										
										
										
											2012-05-26 00:46:12 +00:00
										 |  |  |         scene = context.scene | 
					
						
							|  |  |  |         self.frame_start = scene.frame_start | 
					
						
							|  |  |  |         self.frame_end = scene.frame_end | 
					
						
							|  |  |  |         self.bake_types = {'POSE'} if context.mode == 'POSE' else {'OBJECT'} | 
					
						
							| 
									
										
										
										
											2012-06-19 22:17:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |         wm = context.window_manager | 
					
						
							|  |  |  |         return wm.invoke_props_dialog(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ClearUselessActions(Operator): | 
					
						
							| 
									
										
										
										
											2012-02-08 04:37:37 +00:00
										 |  |  |     """Mark actions with no F-Curves for deletion after save & reload of """ \ | 
					
						
							| 
									
										
										
										
											2011-10-20 07:56:04 +00:00
										 |  |  |     """file preserving \"action libraries\"""" | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |     bl_idname = "anim.clear_useless_actions" | 
					
						
							|  |  |  |     bl_label = "Clear Useless Actions" | 
					
						
							|  |  |  |     bl_options = {'REGISTER', 'UNDO'} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |     only_unused = BoolProperty( | 
					
						
							|  |  |  |             name="Only Unused", | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  |             description="Only unused (Fake User only) actions get considered", | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |             default=True, | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def poll(cls, context): | 
					
						
							| 
									
										
										
										
											2012-01-02 16:18:39 +00:00
										 |  |  |         return bool(bpy.data.actions) | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def execute(self, context): | 
					
						
							|  |  |  |         removed = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for action in bpy.data.actions: | 
					
						
							|  |  |  |             # if only user is "fake" user... | 
					
						
							| 
									
										
										
										
											2013-06-27 03:05:19 +00:00
										 |  |  |             if ((self.only_unused is False) or | 
					
						
							|  |  |  |                 (action.use_fake_user and action.users == 1)): | 
					
						
							| 
									
										
										
										
											2011-09-22 22:51:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 # if it has F-Curves, then it's a "action library" | 
					
						
							|  |  |  |                 # (i.e. walk, wave, jump, etc.) | 
					
						
							|  |  |  |                 # and should be left alone as that's what fake users are for! | 
					
						
							|  |  |  |                 if not action.fcurves: | 
					
						
							|  |  |  |                     # mark action for deletion | 
					
						
							|  |  |  |                     action.user_clear() | 
					
						
							|  |  |  |                     removed += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.report({'INFO'}, "Removed %d empty and/or fake-user only Actions" | 
					
						
							|  |  |  |                               % removed) | 
					
						
							|  |  |  |         return {'FINISHED'} | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UpdateAnimatedTransformConstraint(Operator): | 
					
						
							| 
									
										
										
										
											2014-05-01 16:30:40 +02:00
										 |  |  |     """Update fcurves/drivers affecting Transform constraints (use it with files from 2.70 and earlier)""" | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  |     bl_idname = "anim.update_animated_transform_constraints" | 
					
						
							|  |  |  |     bl_label = "Update Animated Transform Constraints" | 
					
						
							|  |  |  |     bl_options = {'REGISTER', 'UNDO'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     use_convert_to_radians = BoolProperty( | 
					
						
							|  |  |  |             name="Convert To Radians", | 
					
						
							|  |  |  |             description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)", | 
					
						
							|  |  |  |             default=True, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def execute(self, context): | 
					
						
							|  |  |  |         import animsys_refactor | 
					
						
							|  |  |  |         from math import radians | 
					
						
							|  |  |  |         import io | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         from_paths = {"from_max_x", "from_max_y", "from_max_z", "from_min_x", "from_min_y", "from_min_z"} | 
					
						
							|  |  |  |         to_paths = {"to_max_x", "to_max_y", "to_max_z", "to_min_x", "to_min_y", "to_min_z"} | 
					
						
							|  |  |  |         paths = from_paths | to_paths | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def update_cb(base, class_name, old_path, fcurve, options): | 
					
						
							| 
									
										
										
										
											2014-09-17 18:36:17 +10:00
										 |  |  |             # print(options) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  |             def handle_deg2rad(fcurve): | 
					
						
							|  |  |  |                 if fcurve is not None: | 
					
						
							|  |  |  |                     if hasattr(fcurve, "keyframes"): | 
					
						
							|  |  |  |                         for k in fcurve.keyframes: | 
					
						
							|  |  |  |                             k.co.y = radians(k.co.y) | 
					
						
							|  |  |  |                     for mod in fcurve.modifiers: | 
					
						
							|  |  |  |                         if mod.type == 'GENERATOR': | 
					
						
							|  |  |  |                             if mod.mode == 'POLYNOMIAL': | 
					
						
							|  |  |  |                                 mod.coefficients[:] = [radians(c) for c in mod.coefficients] | 
					
						
							|  |  |  |                             else:  # if mod.type == 'POLYNOMIAL_FACTORISED': | 
					
						
							|  |  |  |                                 mod.coefficients[:2] = [radians(c) for c in mod.coefficients[:2]] | 
					
						
							|  |  |  |                         elif mod.type == 'FNGENERATOR': | 
					
						
							|  |  |  |                             mod.amplitude = radians(mod.amplitude) | 
					
						
							|  |  |  |                     fcurve.update() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             data = ... | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 data = eval("base." + old_path) | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             ret = (data, old_path) | 
					
						
							|  |  |  |             if isinstance(base, bpy.types.TransformConstraint) and data is not ...: | 
					
						
							|  |  |  |                 new_path = None | 
					
						
							|  |  |  |                 map_info = base.map_from if old_path in from_paths else base.map_to | 
					
						
							|  |  |  |                 if map_info == 'ROTATION': | 
					
						
							|  |  |  |                     new_path = old_path + "_rot" | 
					
						
							|  |  |  |                     if options is not None and options["use_convert_to_radians"]: | 
					
						
							|  |  |  |                         handle_deg2rad(fcurve) | 
					
						
							|  |  |  |                 elif map_info == 'SCALE': | 
					
						
							|  |  |  |                     new_path = old_path + "_scale" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if new_path is not None: | 
					
						
							|  |  |  |                     data = ... | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         data = eval("base." + new_path) | 
					
						
							|  |  |  |                     except: | 
					
						
							|  |  |  |                         pass | 
					
						
							|  |  |  |                     ret = (data, new_path) | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  |                     # print(ret) | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return ret | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         options = {"use_convert_to_radians": self.use_convert_to_radians} | 
					
						
							|  |  |  |         replace_ls = [("TransformConstraint", p, update_cb, options) for p in paths] | 
					
						
							|  |  |  |         log = io.StringIO() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         animsys_refactor.update_data_paths(replace_ls, log) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         context.scene.frame_set(context.scene.frame_current) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         log = log.getvalue() | 
					
						
							|  |  |  |         if log: | 
					
						
							|  |  |  |             print(log) | 
					
						
							|  |  |  |             text = bpy.data.texts.new("UpdateAnimatedTransformConstraint Report") | 
					
						
							|  |  |  |             text.from_string(log) | 
					
						
							| 
									
										
										
										
											2014-05-22 01:12:00 +10:00
										 |  |  |             self.report({'INFO'}, "Complete report available on '%s' text datablock" % text.name) | 
					
						
							| 
									
										
										
										
											2014-04-28 13:26:01 +02:00
										 |  |  |         return {'FINISHED'} | 
					
						
							| 
									
										
										
										
											2017-03-18 20:03:24 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | classes = ( | 
					
						
							|  |  |  |     ANIM_OT_keying_set_export, | 
					
						
							|  |  |  |     BakeAction, | 
					
						
							|  |  |  |     ClearUselessActions, | 
					
						
							|  |  |  |     UpdateAnimatedTransformConstraint, | 
					
						
							| 
									
										
										
										
											2017-03-20 09:43:18 +11:00
										 |  |  | ) |