From 0beca3b2f2cabd0adfabd8b1332f9a2652a93c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Thu, 21 Apr 2016 18:10:43 +0300 Subject: [PATCH 01/17] Improve Log --- io_export_cryblend/export.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index dce0e42..d525f0c 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -450,6 +450,9 @@ def __export_library_geometries(self, parent_element): geometry_node.setAttribute("id", object_.name) mesh_node = self.__doc.createElement("mesh") + print('') + cbPrint('"{}" object is processing...'.format(object_.name)) + start_time = clock() self.__write_positions(object_, mesh, mesh_node) cbPrint('Positions took {:.4f} sec.'.format(clock() - start_time)) From 72672f7b8ee21e998a0010be5e95d673579d6435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Mon, 13 Jun 2016 02:27:34 +0300 Subject: [PATCH 02/17] Prerequisites for Multiple Animation #201 --- io_export_cryblend/export.py | 48 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index ba2549f..3f3afa1 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -844,23 +844,23 @@ def __export_library_animation_clips_and_animations(self, parent_element): for axis in iter(AXES): animation = self.__get_animation_location( - object_, bone_name, axis) + object_, bone_name, axis, node_name) if animation is not None: libanm.appendChild(animation) for axis in iter(AXES): animation = self.__get_animation_rotation( - object_, bone_name, axis) + object_, bone_name, axis, node_name) if animation is not None: libanm.appendChild(animation) self.__export_instance_animation_parameters( - object_, animation_clip) + object_, animation_clip, node_name) if is_animation: libanmcl.appendChild(animation_clip) - def __export_instance_animation_parameters(self, object_, animation_clip): + def __export_instance_animation_parameters(self, object_, animation_clip, node_name): location_exists = rotation_exists = False for curve in object_.animation_data.action.fcurves: for axis in iter(AXES): @@ -874,20 +874,20 @@ def __export_instance_animation_parameters(self, object_, animation_clip): if location_exists: self.__export_instance_parameter( - object_, animation_clip, "location") + object_, animation_clip, "location", node_name) if rotation_exists: self.__export_instance_parameter( - object_, animation_clip, "rotation_euler") + object_, animation_clip, "rotation_euler", node_name) - def __export_instance_parameter(self, object_, animation_clip, parameter): + def __export_instance_parameter(self, object_, animation_clip, parameter, node_name): for axis in iter(AXES): inst = self.__doc.createElement("instance_animation") inst.setAttribute( - "url", "#{!s}_{!s}_{!s}".format( - object_.name, parameter, axis)) + "url", "#{!s}-{!s}-{!s}_{!s}_{!s}".format( + node_name, node_name, object_.name, parameter, axis)) animation_clip.appendChild(inst) - def __get_animation_location(self, object_, bone_name, axis): + def __get_animation_location(self, object_, bone_name, axis, node_name): attribute_type = "location" multiplier = 1 target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) @@ -896,10 +896,11 @@ def __get_animation_location(self, object_, bone_name, axis): axis, attribute_type, multiplier, - target) + target, + node_name) return animation_element - def __get_animation_rotation(self, object_, bone_name, axis): + def __get_animation_rotation(self, object_, bone_name, axis, node_name): attribute_type = "rotation_euler" multiplier = utils.to_degrees target = "{!s}{!s}{!s}{!s}".format(bone_name, @@ -911,7 +912,8 @@ def __get_animation_rotation(self, object_, bone_name, axis): axis, attribute_type, multiplier, - target) + target, + node_name) return animation_element def __get_animation_attribute(self, @@ -919,8 +921,10 @@ def __get_animation_attribute(self, axis, attribute_type, multiplier, - target): - id_prefix = "{!s}_{!s}_{!s}".format(object_.name, attribute_type, axis) + target, + node_name): + id_prefix = "{!s}-{!s}-{!s}_{!s}_{!s}".format(node_name, node_name, + object_.name, attribute_type, axis) source_prefix = "#{!s}".format(id_prefix) for curve in object_.animation_data.action.fcurves: @@ -1061,13 +1065,13 @@ def __write_export_node(self, group, visual_scene): if (object_.parent is None or object_.type == 'MESH') and \ not utils.is_bone_geometry(object_): root_objects.append(object_) - node = self.__write_visual_scene_node(root_objects, node) + node = self.__write_visual_scene_node(root_objects, node, group) extra = self.__create_cryengine_extra(group) node.appendChild(extra) visual_scene.appendChild(node) - def __write_visual_scene_node(self, objects, parent_node): + def __write_visual_scene_node(self, objects, parent_node, group): for object_ in objects: if object_.type == "MESH" and not utils.is_fakebone(object_): node = self.__doc.createElement("node") @@ -1088,19 +1092,19 @@ def __write_visual_scene_node(self, objects, parent_node): if object_.parent is not None and object_.parent.type == "ARMATURE": self.__write_bone_list( - [utils.get_root_bone(object_.parent)], object_, parent_node) + [utils.get_root_bone(object_.parent)], object_, parent_node, group) elif object_.type == "ARMATURE" and utils.is_physical(object_): self.__write_bone_list( - [utils.get_root_bone(object_)], object_, parent_node) + [utils.get_root_bone(object_)], object_, parent_node, group) return parent_node - def __write_bone_list(self, bones, object_, parent_node): + def __write_bone_list(self, bones, object_, parent_node, group): scene = bpy.context.scene bone_names = [] - node_name = utils.get_armature_node_name(object_) + node_name = utils.get_node_name(group) for bone in bones: props_name = self.__create_props_bone_name(bone, node_name) @@ -1136,7 +1140,7 @@ def __write_bone_list(self, bones, object_, parent_node): parent_node.appendChild(node) if bone.children: - self.__write_bone_list(bone.children, object_, node) + self.__write_bone_list(bone.children, object_, node, group) def __create_instance_for_bone(self, bone, bone_geometry): instance = None From c52c692f73a3b58d9fbb61f110c9f79ecb984543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Tue, 14 Jun 2016 00:54:34 +0300 Subject: [PATCH 03/17] Protected modifiers for export #201 --- io_export_cryblend/export.py | 576 +++++++++++++++++------------------ 1 file changed, 288 insertions(+), 288 deletions(-) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index 3f3afa1..a07719b 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -50,53 +50,53 @@ class CrytekDaeExporter: def __init__(self, config): - self.__config = config - self.__doc = Document() - self.__materials = self.__get_materials() + self._config = config + self._doc = Document() + self._materials = self._get_materials() def export(self): - self.__prepare_for_export() + self._prepare_for_export() - root_element = self.__doc.createElement('collada') + root_element = self._doc.createElement('collada') root_element.setAttribute( "xmlns", "http://www.collada.org/2005/11/COLLADASchema") root_element.setAttribute("version", "1.4.1") - self.__doc.appendChild(root_element) - self.__create_file_header(root_element) + self._doc.appendChild(root_element) + self._create_file_header(root_element) # Just here for future use: - self.__export_library_cameras(root_element) - self.__export_library_lights(root_element) + self._export_library_cameras(root_element) + self._export_library_lights(root_element) ### - self.__export_library_images(root_element) - self.__export_library_effects(root_element) - self.__export_library_materials(root_element) - self.__export_library_geometries(root_element) + self._export_library_images(root_element) + self._export_library_effects(root_element) + self._export_library_materials(root_element) + self._export_library_geometries(root_element) utils.add_fakebones() try: - self.__export_library_controllers(root_element) - self.__export_library_animation_clips_and_animations(root_element) - self.__export_library_visual_scenes(root_element) + self._export_library_controllers(root_element) + self._export_library_animation_clips_and_animations(root_element) + self._export_library_visual_scenes(root_element) except RuntimeError: pass finally: utils.remove_fakebones() - self.__export_scene(root_element) + self._export_scene(root_element) - converter = RCInstance(self.__config) - converter.convert_dae(self.__doc) + converter = RCInstance(self._config) + converter.convert_dae(self._doc) - write_scripts(self.__config) + write_scripts(self._config) - def __get_materials(self): + def _get_materials(self): materials = OrderedDict() material_counter = {} for group in utils.get_export_nodes( - self.__config.export_selected_nodes): + self._config.export_selected_nodes): material_counter[group.name] = 50 for object in group.objects: for slot in object.material_slots: @@ -119,97 +119,97 @@ def __get_materials(self): return materials - def __get_materials_for_object(self, object_): + def _get_materials_for_object(self, object_): materials = OrderedDict() - for material, materialname in self.__materials.items(): + for material, materialname in self._materials.items(): for object_material in object_.data.materials: if material.name == object_material.name: materials[material] = materialname return materials - def __prepare_for_export(self): + def _prepare_for_export(self): utils.clean_file() - if self.__config.apply_modifiers: + if self._config.apply_modifiers: utils.apply_modifiers() - if self.__config.fix_weights: + if self._config.fix_weights: utils.fix_weights() - def __create_file_header(self, parent_element): - asset = self.__doc.createElement('asset') + def _create_file_header(self, parent_element): + asset = self._doc.createElement('asset') parent_element.appendChild(asset) - contributor = self.__doc.createElement('contributor') + contributor = self._doc.createElement('contributor') asset.appendChild(contributor) - author = self.__doc.createElement('author') + author = self._doc.createElement('author') contributor.appendChild(author) - author_name = self.__doc.createTextNode('Blender User') + author_name = self._doc.createTextNode('Blender User') author.appendChild(author_name) - author_tool = self.__doc.createElement('authoring_tool') - author_name_text = self.__doc.createTextNode( - 'CryBlend v{}'.format(self.__config.cryblend_version)) + author_tool = self._doc.createElement('authoring_tool') + author_name_text = self._doc.createTextNode( + 'CryBlend v{}'.format(self._config.cryblend_version)) author_tool.appendChild(author_name_text) contributor.appendChild(author_tool) - created = self.__doc.createElement('created') - created_value = self.__doc.createTextNode( + created = self._doc.createElement('created') + created_value = self._doc.createTextNode( datetime.now().isoformat(' ')) created.appendChild(created_value) asset.appendChild(created) - modified = self.__doc.createElement('modified') + modified = self._doc.createElement('modified') asset.appendChild(modified) - unit = self.__doc.createElement('unit') + unit = self._doc.createElement('unit') unit.setAttribute('name', 'meter') unit.setAttribute('meter', '1') asset.appendChild(unit) - up_axis = self.__doc.createElement('up_axis') - z_up = self.__doc.createTextNode('Z_UP') + up_axis = self._doc.createElement('up_axis') + z_up = self._doc.createTextNode('Z_UP') up_axis.appendChild(z_up) asset.appendChild(up_axis) - def __export_library_cameras(self, root_element): - library_cameras = self.__doc.createElement('library_cameras') + def _export_library_cameras(self, root_element): + library_cameras = self._doc.createElement('library_cameras') root_element.appendChild(library_cameras) - def __export_library_lights(self, root_element): - library_lights = self.__doc.createElement('library_lights') + def _export_library_lights(self, root_element): + library_lights = self._doc.createElement('library_lights') root_element.appendChild(library_lights) #------------------------------------------------------------------ # Library Images: #------------------------------------------------------------------ - def __export_library_images(self, parent_element): - library_images = self.__doc.createElement('library_images') + def _export_library_images(self, parent_element): + library_images = self._doc.createElement('library_images') parent_element.appendChild(library_images) if bpy.context.scene.render.engine == 'CYCLES': - images = self.__get_nodes_images_in_export_nodes() + images = self._get_nodes_images_in_export_nodes() else: - images = self.__get_image_textures_in_export_nodes() + images = self._get_image_textures_in_export_nodes() for image in images: - image_element = self.__export_library_image(image) + image_element = self._export_library_image(image) library_images.appendChild(image_element) - if self.__config.do_textures: - self.__convert_images_to_dds(images) + if self._config.do_textures: + self._convert_images_to_dds(images) - def __export_library_image(self, image): + def _export_library_image(self, image): image_path = utils.get_image_path_for_game(image, - self.__config.game_dir) + self._config.game_dir) - image_element = self.__doc.createElement('image') + image_element = self._doc.createElement('image') image_element.setAttribute('id', image.name) image_element.setAttribute('name', image.name) - init_from = self.__doc.createElement('init_from') - path_node = self.__doc.createTextNode(image_path) + init_from = self._doc.createElement('init_from') + path_node = self._doc.createTextNode(image_path) init_from.appendChild(path_node) image_element.appendChild(init_from) return image_element - def __get_nodes_images_in_export_nodes(self): + def _get_nodes_images_in_export_nodes(self): images = [] nodes = utils.get_type("texture_nodes") @@ -226,7 +226,7 @@ def __get_nodes_images_in_export_nodes(self): # return only unique images return list(set(images)) - def __get_image_textures_in_export_nodes(self): + def _get_image_textures_in_export_nodes(self): images = [] textures = utils.get_type('textures') @@ -242,55 +242,55 @@ def __get_image_textures_in_export_nodes(self): # return only unique images return list(set(images)) - def __convert_images_to_dds(self, images): - converter = RCInstance(self.__config) + def _convert_images_to_dds(self, images): + converter = RCInstance(self._config) converter.convert_tif(images) #-------------------------------------------------------------- # Library Effects: #-------------------------------------------------------------- - def __export_library_effects(self, parent_element): - current_element = self.__doc.createElement('library_effects') + def _export_library_effects(self, parent_element): + current_element = self._doc.createElement('library_effects') parent_element.appendChild(current_element) - for material, materialname in self.__materials.items(): - self.__export_library_effects_material( + for material, materialname in self._materials.items(): + self._export_library_effects_material( material, materialname, current_element) - def __export_library_effects_material( + def _export_library_effects_material( self, material, materialname, current_element): images = [[], [], []] is_cycles_render = bpy.context.scene.render.engine == 'CYCLES' if is_cycles_render: - self.__get_cycles_render_images(material, images) + self._get_cycles_render_images(material, images) else: - self.__get_blender_render_images(material, images) + self._get_blender_render_images(material, images) - effect_node = self.__doc.createElement("effect") + effect_node = self._doc.createElement("effect") effect_node.setAttribute("id", "{}_fx".format(materialname)) - profile_node = self.__doc.createElement("profile_COMMON") + profile_node = self._doc.createElement("profile_COMMON") for image in images: if len(image) != 0: profile_node.appendChild(image[1]) profile_node.appendChild(image[2]) - technique_common = self.__doc.createElement("technique") + technique_common = self._doc.createElement("technique") technique_common.setAttribute("sid", "common") - phong = self.__create_material_node(material, images) + phong = self._create_material_node(material, images) technique_common.appendChild(phong) profile_node.appendChild(technique_common) - extra = self.__create_double_sided_extra("GOOGLEEARTH") + extra = self._create_double_sided_extra("GOOGLEEARTH") profile_node.appendChild(extra) effect_node.appendChild(profile_node) - extra = self.__create_double_sided_extra("MAX3D") + extra = self._create_double_sided_extra("MAX3D") effect_node.appendChild(extra) current_element.appendChild(effect_node) - def __get_cycles_render_images(self, material, images): + def _get_cycles_render_images(self, material, images): cycles_nodes = utils.get_texture_nodes_for_material(material) for cycles_node in cycles_nodes: image = cycles_node.image @@ -298,7 +298,7 @@ def __get_cycles_render_images(self, material, images): raise exceptions.CryBlendException( "One of texture slots has no image assigned.") - surface, sampler = self.__create_surface_and_sampler(image.name) + surface, sampler = self._create_surface_and_sampler(image.name) if cycles_node.name == "Image Texture": images[0] = [image.name, surface, sampler] if cycles_node.name == "Specular": @@ -306,7 +306,7 @@ def __get_cycles_render_images(self, material, images): if cycles_node.name == "Normal": images[2] = [image.name, surface, sampler] - def __get_blender_render_images(self, material, images): + def _get_blender_render_images(self, material, images): texture_slots = utils.get_texture_slots_for_material(material) for texture_slot in texture_slots: image = texture_slot.texture.image @@ -314,7 +314,7 @@ def __get_blender_render_images(self, material, images): raise exceptions.CryBlendException( "One of texture slots has no image assigned.") - surface, sampler = self.__create_surface_and_sampler(image.name) + surface, sampler = self._create_surface_and_sampler(image.name) if texture_slot.use_map_color_diffuse: images[0] = [image.name, surface, sampler] if texture_slot.use_map_color_spec: @@ -322,21 +322,21 @@ def __get_blender_render_images(self, material, images): if texture_slot.use_map_normal: images[2] = [image.name, surface, sampler] - def __create_surface_and_sampler(self, image_name): - surface = self.__doc.createElement("newparam") + def _create_surface_and_sampler(self, image_name): + surface = self._doc.createElement("newparam") surface.setAttribute("sid", "{}-surface".format(image_name)) - surface_node = self.__doc.createElement("surface") + surface_node = self._doc.createElement("surface") surface_node.setAttribute("type", "2D") - init_from_node = self.__doc.createElement("init_from") - temp_node = self.__doc.createTextNode(image_name) + init_from_node = self._doc.createElement("init_from") + temp_node = self._doc.createTextNode(image_name) init_from_node.appendChild(temp_node) surface_node.appendChild(init_from_node) surface.appendChild(surface_node) - sampler = self.__doc.createElement("newparam") + sampler = self._doc.createElement("newparam") sampler.setAttribute("sid", "{}-sampler".format(image_name)) - sampler_node = self.__doc.createElement("sampler2D") - source_node = self.__doc.createElement("source") - temp_node = self.__doc.createTextNode( + sampler_node = self._doc.createElement("sampler2D") + source_node = self._doc.createElement("source") + temp_node = self._doc.createTextNode( "{}-surface".format(image_name)) source_node.appendChild(temp_node) sampler_node.appendChild(source_node) @@ -344,22 +344,22 @@ def __create_surface_and_sampler(self, image_name): return surface, sampler - def __create_material_node(self, material, images): - phong = self.__doc.createElement("phong") + def _create_material_node(self, material, images): + phong = self._doc.createElement("phong") - emission = self.__create_color_node(material, "emission") - ambient = self.__create_color_node(material, "ambient") + emission = self._create_color_node(material, "emission") + ambient = self._create_color_node(material, "ambient") if len(images[0]) != 0: - diffuse = self.__create_texture_node(images[0][0], "diffuse") + diffuse = self._create_texture_node(images[0][0], "diffuse") else: - diffuse = self.__create_color_node(material, "diffuse") + diffuse = self._create_color_node(material, "diffuse") if len(images[1]) != 0: - specular = self.__create_texture_node(images[1][0], "specular") + specular = self._create_texture_node(images[1][0], "specular") else: - specular = self.__create_color_node(material, "specular") + specular = self._create_color_node(material, "specular") - shininess = self.__create_attribute_node(material, "shininess") - index_refraction = self.__create_attribute_node( + shininess = self._create_attribute_node(material, "shininess") + index_refraction = self._create_attribute_node( material, "index_refraction") phong.appendChild(emission) @@ -369,47 +369,47 @@ def __create_material_node(self, material, images): phong.appendChild(shininess) phong.appendChild(index_refraction) if len(images[2]) != 0: - normal = self.__create_texture_node(images[2][0], "normal") + normal = self._create_texture_node(images[2][0], "normal") phong.appendChild(normal) return phong - def __create_color_node(self, material, type_): - node = self.__doc.createElement(type_) - color = self.__doc.createElement("color") + def _create_color_node(self, material, type_): + node = self._doc.createElement(type_) + color = self._doc.createElement("color") color.setAttribute("sid", type_) col = utils.get_material_color(material, type_) - color_text = self.__doc.createTextNode(col) + color_text = self._doc.createTextNode(col) color.appendChild(color_text) node.appendChild(color) return node - def __create_texture_node(self, image_name, type_): - node = self.__doc.createElement(type_) - texture = self.__doc.createElement("texture") + def _create_texture_node(self, image_name, type_): + node = self._doc.createElement(type_) + texture = self._doc.createElement("texture") texture.setAttribute("texture", "{}-sampler".format(image_name)) node.appendChild(texture) return node - def __create_attribute_node(self, material, type_): - node = self.__doc.createElement(type_) - float = self.__doc.createElement("float") + def _create_attribute_node(self, material, type_): + node = self._doc.createElement(type_) + float = self._doc.createElement("float") float.setAttribute("sid", type_) val = utils.get_material_attribute(material, type_) - value = self.__doc.createTextNode(val) + value = self._doc.createTextNode(val) float.appendChild(value) node.appendChild(float) return node - def __create_double_sided_extra(self, profile): - extra = self.__doc.createElement("extra") - technique = self.__doc.createElement("technique") + def _create_double_sided_extra(self, profile): + extra = self._doc.createElement("extra") + technique = self._doc.createElement("technique") technique.setAttribute("profile", profile) - double_sided = self.__doc.createElement("double_sided") - double_sided_value = self.__doc.createTextNode("1") + double_sided = self._doc.createElement("double_sided") + double_sided_value = self._doc.createTextNode("1") double_sided.appendChild(double_sided_value) technique.appendChild(double_sided) extra.appendChild(technique) @@ -420,13 +420,13 @@ def __create_double_sided_extra(self, profile): # Library Materials: #------------------------------------------------------------------ - def __export_library_materials(self, parent_element): - library_materials = self.__doc.createElement('library_materials') + def _export_library_materials(self, parent_element): + library_materials = self._doc.createElement('library_materials') - for material, materialname in self.__materials.items(): - material_element = self.__doc.createElement('material') + for material, materialname in self._materials.items(): + material_element = self._doc.createElement('material') material_element.setAttribute('id', materialname) - instance_effect = self.__doc.createElement('instance_effect') + instance_effect = self._doc.createElement('instance_effect') instance_effect.setAttribute('url', '#{}_fx'.format(materialname)) material_element.appendChild(instance_effect) library_materials.appendChild(material_element) @@ -437,8 +437,8 @@ def __export_library_materials(self, parent_element): # Library Geometries: #------------------------------------------------------------------ - def __export_library_geometries(self, parent_element): - libgeo = self.__doc.createElement("library_geometries") + def _export_library_geometries(self, parent_element): + libgeo = self._doc.createElement("library_geometries") parent_element.appendChild(libgeo) for object_ in utils.get_type("geometry"): utils.set_active(object_) @@ -447,45 +447,45 @@ def __export_library_geometries(self, parent_element): object_.data.update(calc_tessface=1) mesh = object_.data object_.name = object_.name - geometry_node = self.__doc.createElement("geometry") + geometry_node = self._doc.createElement("geometry") geometry_node.setAttribute("id", object_.name) - mesh_node = self.__doc.createElement("mesh") + mesh_node = self._doc.createElement("mesh") print('') cbPrint('"{}" object is processing...'.format(object_.name)) start_time = clock() - self.__write_positions(object_, mesh, mesh_node) + self._write_positions(object_, mesh, mesh_node) cbPrint('Positions took {:.4f} sec.'.format(clock() - start_time)) start_time = clock() - self.__write_normals(object_, mesh, mesh_node) + self._write_normals(object_, mesh, mesh_node) cbPrint('Normals took {:.4f} sec.'.format(clock() - start_time)) start_time = clock() - self.__write_uvs(object_, mesh, mesh_node) + self._write_uvs(object_, mesh, mesh_node) cbPrint('UVs took {:.4f} sec.'.format(clock() - start_time)) start_time = clock() - self.__write_vertex_colors(object_, mesh, mesh_node) + self._write_vertex_colors(object_, mesh, mesh_node) cbPrint( 'Vertex colors took {:.4f} sec.'.format( clock() - start_time)) start_time = clock() - self.__write_vertices(object_, mesh, mesh_node) + self._write_vertices(object_, mesh, mesh_node) cbPrint('Vertices took {:.4f} sec.'.format(clock() - start_time)) start_time = clock() - self.__write_polylist(object_, mesh, mesh_node) + self._write_polylist(object_, mesh, mesh_node) cbPrint('Polylist took {:.4f} sec.'.format(clock() - start_time)) - extra = self.__create_double_sided_extra("MAYA") + extra = self._create_double_sided_extra("MAYA") mesh_node.appendChild(extra) geometry_node.appendChild(mesh_node) libgeo.appendChild(geometry_node) - def __write_positions(self, object_, mesh, root): + def _write_positions(self, object_, mesh, root): float_positions = [] for vertex in mesh.vertices: float_positions.extend(vertex.co) @@ -494,7 +494,7 @@ def __write_positions(self, object_, mesh, root): source = utils.write_source(id_, "float", float_positions, "XYZ") root.appendChild(source) - def __write_normals(self, object_, mesh, root): + def _write_normals(self, object_, mesh, root): float_normals = [] float_normals_count = "" @@ -504,7 +504,7 @@ def __write_normals(self, object_, mesh, root): vertex = mesh.vertices[vert] float_normals.extend(vertex.normal) else: - if self.__config.average_planar: + if self._config.average_planar: count = 1 nx = face.normal.x ny = face.normal.y @@ -528,7 +528,7 @@ def __write_normals(self, object_, mesh, root): source = utils.write_source(id_, "float", float_normals, "XYZ") root.appendChild(source) - def __write_uvs(self, object_, mesh, root): + def _write_uvs(self, object_, mesh, root): uvdata = object_.data.tessface_uv_textures if uvdata is None: cbPrint("Your UV map is missing, adding...") @@ -550,7 +550,7 @@ def __write_uvs(self, object_, mesh, root): source = utils.write_source(id_, "float", float_uvs, "ST") root.appendChild(source) - def __write_vertex_colors(self, object_, mesh, root): + def _write_vertex_colors(self, object_, mesh, root): float_colors = [] alpha_found = False @@ -576,16 +576,16 @@ def __write_vertex_colors(self, object_, mesh, root): source = utils.write_source(id_, "float", float_colors, params) root.appendChild(source) - def __write_vertices(self, object_, mesh, root): - vertices = self.__doc.createElement("vertices") + def _write_vertices(self, object_, mesh, root): + vertices = self._doc.createElement("vertices") vertices.setAttribute("id", "{}-vertices".format(object_.name)) input = utils.write_input(object_.name, None, "positions", "POSITION") vertices.appendChild(input) root.appendChild(vertices) - def __write_polylist(self, object_, mesh, root): + def _write_polylist(self, object_, mesh, root): matindex = 0 - for material, materialname in self.__get_materials_for_object( + for material, materialname in self._get_materials_for_object( object_).items(): vert_data = '' verts_per_poly = '' @@ -598,7 +598,7 @@ def __write_polylist(self, object_, mesh, root): face.vertices), ' ') poly_count += 1 for vert in face.vertices: - data = self.__write_vertex_data( + data = self._write_vertex_data( mesh, face, vert, normal, texcoord) vert_data = join(vert_data, data) texcoord += 1 @@ -614,7 +614,7 @@ def __write_polylist(self, object_, mesh, root): matindex += 1 continue - polylist = self.__doc.createElement('polylist') + polylist = self._doc.createElement('polylist') polylist.setAttribute('material', materialname) polylist.setAttribute('count', str(poly_count)) @@ -648,12 +648,12 @@ def __write_polylist(self, object_, mesh, root): for input in inputs: polylist.appendChild(input) - vcount = self.__doc.createElement('vcount') - vcount_text = self.__doc.createTextNode(verts_per_poly) + vcount = self._doc.createElement('vcount') + vcount_text = self._doc.createTextNode(verts_per_poly) vcount.appendChild(vcount_text) - p = self.__doc.createElement('p') - p_text = self.__doc.createTextNode(vert_data) + p = self._doc.createElement('p') + p_text = self._doc.createTextNode(vert_data) p.appendChild(p_text) polylist.appendChild(vcount) @@ -661,7 +661,7 @@ def __write_polylist(self, object_, mesh, root): root.appendChild(polylist) matindex += 1 - def __write_vertex_data(self, mesh, face, vert, normal, texcoord): + def _write_vertex_data(self, mesh, face, vert, normal, texcoord): if face.use_smooth: normal = vert @@ -676,60 +676,60 @@ def __write_vertex_data(self, mesh, face, vert, normal, texcoord): # --> Skin Geometry, Weights, Transform Matrices # ------------------------------------------------------------------------- - def __export_library_controllers(self, parent_element): - library_node = self.__doc.createElement("library_controllers") + def _export_library_controllers(self, parent_element): + library_node = self._doc.createElement("library_controllers") for object_ in utils.get_type("geometry"): if not utils.is_bone_geometry(object_): armature = utils.get_armature_for_object(object_) if armature is not None: - self.__process_bones(library_node, + self._process_bones(library_node, object_, armature) parent_element.appendChild(library_node) - def __process_bones(self, parent_node, object_, armature): + def _process_bones(self, parent_node, object_, armature): mesh = object_.data id_ = "{!s}_{!s}".format(armature.name, object_.name) - controller_node = self.__doc.createElement("controller") + controller_node = self._doc.createElement("controller") parent_node.appendChild(controller_node) controller_node.setAttribute("id", id_) - skin_node = self.__doc.createElement("skin") + skin_node = self._doc.createElement("skin") skin_node.setAttribute("source", "#{}".format(object_.name)) controller_node.appendChild(skin_node) - bind_shape_matrix = self.__doc.createElement("bind_shape_matrix") + bind_shape_matrix = self._doc.createElement("bind_shape_matrix") utils.write_matrix(Matrix(), bind_shape_matrix) skin_node.appendChild(bind_shape_matrix) - self.__process_bone_joints(object_, armature, skin_node) - self.__process_bone_matrices(object_, armature, skin_node) - self.__process_bone_weights(object_, armature, skin_node) + self._process_bone_joints(object_, armature, skin_node) + self._process_bone_matrices(object_, armature, skin_node) + self._process_bone_weights(object_, armature, skin_node) - joints = self.__doc.createElement("joints") + joints = self._doc.createElement("joints") input = utils.write_input(id_, None, "joints", "JOINT") joints.appendChild(input) input = utils.write_input(id_, None, "matrices", "INV_BIND_MATRIX") joints.appendChild(input) skin_node.appendChild(joints) - def __process_bone_joints(self, object_, armature, skin_node): + def _process_bone_joints(self, object_, armature, skin_node): bones = utils.get_bones(armature) id_ = "{!s}_{!s}-joints".format(armature.name, object_.name) node_name = utils.get_armature_node_name(object_) bone_names = [] for bone in bones: - props_name = self.__create_props_bone_name(bone, node_name) + props_name = self._create_props_bone_name(bone, node_name) bone_name = "{!s}{!s}".format(bone.name, props_name) bone_names.append(bone_name) source = utils.write_source(id_, "IDREF", bone_names, []) skin_node.appendChild(source) - def __process_bone_matrices(self, object_, armature, skin_node): + def _process_bone_matrices(self, object_, armature, skin_node): bones = utils.get_bones(armature) bone_matrices = [] @@ -745,7 +745,7 @@ def __process_bone_matrices(self, object_, armature, skin_node): source = utils.write_source(id_, "float4x4", bone_matrices, []) skin_node.appendChild(source) - def __process_bone_weights(self, object_, armature, skin_node): + def _process_bone_weights(self, object_, armature, skin_node): bones = utils.get_bones(armature) group_weights = [] @@ -780,7 +780,7 @@ def __process_bone_weights(self, object_, armature, skin_node): source = utils.write_source(id_, "float", group_weights, []) skin_node.appendChild(source) - vertex_weights = self.__doc.createElement("vertex_weights") + vertex_weights = self._doc.createElement("vertex_weights") vertex_weights.setAttribute("count", str(len(object_.data.vertices))) id_ = "{!s}_{!s}".format(armature.name, object_.name) @@ -789,13 +789,13 @@ def __process_bone_weights(self, object_, armature, skin_node): input = utils.write_input(id_, 1, "weights", "WEIGHT") vertex_weights.appendChild(input) - vcount = self.__doc.createElement("vcount") - vcount_text = self.__doc.createTextNode(vertex_groups_lengths) + vcount = self._doc.createElement("vcount") + vcount_text = self._doc.createTextNode(vertex_groups_lengths) vcount.appendChild(vcount_text) vertex_weights.appendChild(vcount) - v = self.__doc.createElement("v") - v_text = self.__doc.createTextNode(vw) + v = self._doc.createElement("v") + v_text = self._doc.createTextNode(vw) v.appendChild(v_text) vertex_weights.appendChild(v) @@ -805,9 +805,9 @@ def __process_bone_weights(self, object_, armature, skin_node): # Library Animation and Clips: --> Animations, Fakebones, Bone Geometries # ----------------------------------------------------------------------------- - def __export_library_animation_clips_and_animations(self, parent_element): - libanmcl = self.__doc.createElement("library_animation_clips") - libanm = self.__doc.createElement("library_animations") + def _export_library_animation_clips_and_animations(self, parent_element): + libanmcl = self._doc.createElement("library_animation_clips") + libanm = self._doc.createElement("library_animations") parent_element.appendChild(libanmcl) parent_element.appendChild(libanm) @@ -815,10 +815,10 @@ def __export_library_animation_clips_and_animations(self, parent_element): ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") for group in utils.get_export_nodes( - self.__config.export_selected_nodes): + self._config.export_selected_nodes): node_type = utils.get_node_type(group) if node_type in ALLOWED_NODE_TYPES: - animation_clip = self.__doc.createElement("animation_clip") + animation_clip = self._doc.createElement("animation_clip") node_name = utils.get_node_name(group) animation_clip.setAttribute( "id", "{!s}-{!s}".format(node_name, node_name)) @@ -838,29 +838,29 @@ def __export_library_animation_clips_and_animations(self, parent_element): is_animation = True - props_name = self.__create_props_bone_name( + props_name = self._create_props_bone_name( object_, node_name) bone_name = "{!s}{!s}".format(object_.name, props_name) for axis in iter(AXES): - animation = self.__get_animation_location( + animation = self._get_animation_location( object_, bone_name, axis, node_name) if animation is not None: libanm.appendChild(animation) for axis in iter(AXES): - animation = self.__get_animation_rotation( + animation = self._get_animation_rotation( object_, bone_name, axis, node_name) if animation is not None: libanm.appendChild(animation) - self.__export_instance_animation_parameters( + self._export_instance_animation_parameters( object_, animation_clip, node_name) if is_animation: libanmcl.appendChild(animation_clip) - def __export_instance_animation_parameters(self, object_, animation_clip, node_name): + def _export_instance_animation_parameters(self, object_, animation_clip, node_name): location_exists = rotation_exists = False for curve in object_.animation_data.action.fcurves: for axis in iter(AXES): @@ -873,26 +873,26 @@ def __export_instance_animation_parameters(self, object_, animation_clip, node_n break if location_exists: - self.__export_instance_parameter( + self._export_instance_parameter( object_, animation_clip, "location", node_name) if rotation_exists: - self.__export_instance_parameter( + self._export_instance_parameter( object_, animation_clip, "rotation_euler", node_name) - def __export_instance_parameter(self, object_, animation_clip, parameter, node_name): + def _export_instance_parameter(self, object_, animation_clip, parameter, node_name): for axis in iter(AXES): - inst = self.__doc.createElement("instance_animation") + inst = self._doc.createElement("instance_animation") inst.setAttribute( "url", "#{!s}-{!s}-{!s}_{!s}_{!s}".format( node_name, node_name, object_.name, parameter, axis)) animation_clip.appendChild(inst) - def __get_animation_location(self, object_, bone_name, axis, node_name): + def _get_animation_location(self, object_, bone_name, axis, node_name): attribute_type = "location" multiplier = 1 target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) - animation_element = self.__get_animation_attribute(object_, + animation_element = self._get_animation_attribute(object_, axis, attribute_type, multiplier, @@ -900,7 +900,7 @@ def __get_animation_location(self, object_, bone_name, axis, node_name): node_name) return animation_element - def __get_animation_rotation(self, object_, bone_name, axis, node_name): + def _get_animation_rotation(self, object_, bone_name, axis, node_name): attribute_type = "rotation_euler" multiplier = utils.to_degrees target = "{!s}{!s}{!s}{!s}".format(bone_name, @@ -908,7 +908,7 @@ def __get_animation_rotation(self, object_, bone_name, axis, node_name): axis, ".ANGLE") - animation_element = self.__get_animation_attribute(object_, + animation_element = self._get_animation_attribute(object_, axis, attribute_type, multiplier, @@ -916,7 +916,7 @@ def __get_animation_rotation(self, object_, bone_name, axis, node_name): node_name) return animation_element - def __get_animation_attribute(self, + def _get_animation_attribute(self, object_, axis, attribute_type, @@ -954,16 +954,16 @@ def __get_animation_attribute(self, sources["outangent"].extend( [utils.frame_to_time(khrx), khry]) - animation_element = self.__doc.createElement("animation") + animation_element = self._doc.createElement("animation") animation_element.setAttribute("id", id_prefix) for type_, data in sources.items(): - anim_node = self.__create_animation_node( + anim_node = self._create_animation_node( type_, data, id_prefix) animation_element.appendChild(anim_node) - sampler = self.__create_sampler(id_prefix, source_prefix) - channel = self.__doc.createElement("channel") + sampler = self._create_sampler(id_prefix, source_prefix) + channel = self._doc.createElement("channel") channel.setAttribute( "source", "{!s}-sampler".format(source_prefix)) channel.setAttribute("target", target) @@ -973,7 +973,7 @@ def __get_animation_attribute(self, return animation_element - def __create_animation_node(self, type_, data, id_prefix): + def _create_animation_node(self, type_, data, id_prefix): id_ = "{!s}-{!s}".format(id_prefix, type_) type_map = { "input": ["float", ["TIME"]], @@ -988,25 +988,25 @@ def __create_animation_node(self, type_, data, id_prefix): return source - def __create_sampler(self, id_prefix, source_prefix): - sampler = self.__doc.createElement("sampler") + def _create_sampler(self, id_prefix, source_prefix): + sampler = self._doc.createElement("sampler") sampler.setAttribute("id", "{!s}-sampler".format(id_prefix)) - input = self.__doc.createElement("input") + input = self._doc.createElement("input") input.setAttribute("semantic", "INPUT") input.setAttribute("source", "{!s}-input".format(source_prefix)) - output = self.__doc.createElement("input") + output = self._doc.createElement("input") output.setAttribute("semantic", "OUTPUT") output.setAttribute("source", "{!s}-output".format(source_prefix)) - interpolation = self.__doc.createElement("input") + interpolation = self._doc.createElement("input") interpolation.setAttribute("semantic", "INTERPOLATION") interpolation.setAttribute( "source", "{!s}-interpolation".format(source_prefix)) - intangent = self.__doc.createElement("input") + intangent = self._doc.createElement("input") intangent.setAttribute("semantic", "IN_TANGENT") intangent.setAttribute( "source", "{!s}-intangent".format(source_prefix)) - outangent = self.__doc.createElement("input") + outangent = self._doc.createElement("input") outangent.setAttribute("semantic", "OUT_TANGENT") outangent.setAttribute( "source", "{!s}-outangent".format(source_prefix)) @@ -1024,40 +1024,40 @@ def __create_sampler(self, id_prefix, source_prefix): # Transformations, and Instance URL (_boneGeometry) and extras. # --------------------------------------------------------------------- - def __export_library_visual_scenes(self, parent_element): - current_element = self.__doc.createElement("library_visual_scenes") - visual_scene = self.__doc.createElement("visual_scene") + def _export_library_visual_scenes(self, parent_element): + current_element = self._doc.createElement("library_visual_scenes") + visual_scene = self._doc.createElement("visual_scene") visual_scene.setAttribute("id", "scene") visual_scene.setAttribute("name", "scene") current_element.appendChild(visual_scene) parent_element.appendChild(current_element) - if utils.get_export_nodes(self.__config.export_selected_nodes): + if utils.get_export_nodes(self._config.export_selected_nodes): if utils.are_duplicate_nodes(): message = "Duplicate Node Names" bpy.ops.screen.display_error('INVOKE_DEFAULT', message=message) for group in utils.get_export_nodes( - self.__config.export_selected_nodes): - self.__write_export_node(group, visual_scene) + self._config.export_selected_nodes): + self._write_export_node(group, visual_scene) else: pass # TODO: Handle No Export Nodes Error - def __write_export_node(self, group, visual_scene): - if not self.__config.export_for_lumberyard: + def _write_export_node(self, group, visual_scene): + if not self._config.export_for_lumberyard: node_name = "CryExportNode_{}".format(utils.get_node_name(group)) - node = self.__doc.createElement("node") + node = self._doc.createElement("node") node.setAttribute("id", node_name) node.setIdAttribute("id") else: node_name = "{}".format(utils.get_node_name(group)) - node = self.__doc.createElement("node") + node = self._doc.createElement("node") node.setAttribute("id", node_name) node.setAttribute("LumberyardExportNode", "1") node.setIdAttribute("id") bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) - self.__write_transforms(bpy.context.active_object, node) + self._write_transforms(bpy.context.active_object, node) bpy.ops.object.delete(use_global=False) root_objects = [] @@ -1065,69 +1065,69 @@ def __write_export_node(self, group, visual_scene): if (object_.parent is None or object_.type == 'MESH') and \ not utils.is_bone_geometry(object_): root_objects.append(object_) - node = self.__write_visual_scene_node(root_objects, node, group) + node = self._write_visual_scene_node(root_objects, node, group) - extra = self.__create_cryengine_extra(group) + extra = self._create_cryengine_extra(group) node.appendChild(extra) visual_scene.appendChild(node) - def __write_visual_scene_node(self, objects, parent_node, group): + def _write_visual_scene_node(self, objects, parent_node, group): for object_ in objects: if object_.type == "MESH" and not utils.is_fakebone(object_): - node = self.__doc.createElement("node") + node = self._doc.createElement("node") node.setAttribute("id", object_.name) node.setIdAttribute("id") - self.__write_transforms(object_, node) + self._write_transforms(object_, node) - instance = self.__create_instance(object_) + instance = self._create_instance(object_) if instance is not None: node.appendChild(instance) - extra = self.__create_cryengine_extra(object_) + extra = self._create_cryengine_extra(object_) if extra is not None: node.appendChild(extra) parent_node.appendChild(node) if object_.parent is not None and object_.parent.type == "ARMATURE": - self.__write_bone_list( + self._write_bone_list( [utils.get_root_bone(object_.parent)], object_, parent_node, group) elif object_.type == "ARMATURE" and utils.is_physical(object_): - self.__write_bone_list( + self._write_bone_list( [utils.get_root_bone(object_)], object_, parent_node, group) return parent_node - def __write_bone_list(self, bones, object_, parent_node, group): + def _write_bone_list(self, bones, object_, parent_node, group): scene = bpy.context.scene bone_names = [] node_name = utils.get_node_name(group) for bone in bones: - props_name = self.__create_props_bone_name(bone, node_name) - props_ik = self.__create_ik_properties(bone, object_) + props_name = self._create_props_bone_name(bone, node_name) + props_ik = self._create_ik_properties(bone, object_) bone_name = join(bone.name, props_name, props_ik) bone_names.append(bone_name) - node = self.__doc.createElement("node") + node = self._doc.createElement("node") node.setAttribute("id", bone_name) node.setAttribute("name", bone_name) node.setIdAttribute("id") fakebone = utils.get_fakebone(bone.name) if fakebone is not None: - self.__write_transforms(fakebone, node) + self._write_transforms(fakebone, node) bone_geometry = utils.get_bone_geometry(bone.name) if bone_geometry is not None: - instance = self.__create_instance_for_bone( + instance = self._create_instance_for_bone( bone, bone_geometry) node.appendChild(instance) - extra = self.__create_physic_proxy_for_bone( + extra = self._create_physic_proxy_for_bone( object_.parent, bone) if extra is not None: node.appendChild(extra) @@ -1135,26 +1135,26 @@ def __write_bone_list(self, bones, object_, parent_node, group): elif utils.is_physical(bone): bone_geometry = utils.get_bone_geometry(bone.name) if bone_geometry is not None: - self.__write_transforms(bone_geometry, node) + self._write_transforms(bone_geometry, node) parent_node.appendChild(node) if bone.children: - self.__write_bone_list(bone.children, object_, node, group) + self._write_bone_list(bone.children, object_, node, group) - def __create_instance_for_bone(self, bone, bone_geometry): + def _create_instance_for_bone(self, bone, bone_geometry): instance = None - instance = self.__doc.createElement("instance_geometry") + instance = self._doc.createElement("instance_geometry") instance.setAttribute("url", "#{}_boneGeometry".format(bone.name)) - bm = self.__doc.createElement("bind_material") - tc = self.__doc.createElement("technique_common") + bm = self._doc.createElement("bind_material") + tc = self._doc.createElement("technique_common") for mat in bone_geometry.material_slots: - im = self.__doc.createElement("instance_material") + im = self._doc.createElement("instance_material") im.setAttribute("symbol", mat.name) im.setAttribute("target", "#{}".format(mat.name)) - bvi = self.__doc.createElement("bind_vertex_input") + bvi = self._doc.createElement("bind_vertex_input") bvi.setAttribute("semantic", "UVMap") bvi.setAttribute("input_semantic", "TEXCOORD") bvi.setAttribute("input_set", "0") @@ -1166,18 +1166,18 @@ def __create_instance_for_bone(self, bone, bone_geometry): return instance - def __create_physic_proxy_for_bone(self, object_, bone): + def _create_physic_proxy_for_bone(self, object_, bone): extra = None try: bonePhys = object_.pose.bones[bone.name]['phys_proxy'] cbPrint(bone.name + " physic proxy is " + bonePhys) - extra = self.__doc.createElement("extra") - techcry = self.__doc.createElement("technique") + extra = self._doc.createElement("extra") + techcry = self._doc.createElement("technique") techcry.setAttribute("profile", "CryEngine") - prop2 = self.__doc.createElement("properties") + prop2 = self._doc.createElement("properties") - cryprops = self.__doc.createTextNode(bonePhys) + cryprops = self._doc.createTextNode(bonePhys) prop2.appendChild(cryprops) techcry.appendChild(prop2) extra.appendChild(techcry) @@ -1186,10 +1186,10 @@ def __create_physic_proxy_for_bone(self, object_, bone): return extra - def __write_transforms(self, object_, node): - trans = self.__create_translation_node(object_) - rotx, roty, rotz = self.__create_rotation_node(object_) - scale = self.__create_scale_node(object_) + def _write_transforms(self, object_, node): + trans = self._create_translation_node(object_) + rotx, roty, rotz = self._create_rotation_node(object_) + scale = self._create_scale_node(object_) node.appendChild(trans) node.appendChild(rotx) @@ -1197,74 +1197,74 @@ def __write_transforms(self, object_, node): node.appendChild(rotz) node.appendChild(scale) - def __create_translation_node(self, object_): - trans = self.__doc.createElement("translate") + def _create_translation_node(self, object_): + trans = self._doc.createElement("translate") trans.setAttribute("sid", "translation") - trans_text = self.__doc.createTextNode("{:f} {:f} {:f}".format( + trans_text = self._doc.createTextNode("{:f} {:f} {:f}".format( * object_.location)) trans.appendChild(trans_text) return trans - def __create_rotation_node(self, object_): - rotx = self.__write_rotation( + def _create_rotation_node(self, object_): + rotx = self._write_rotation( "X", "1 0 0 {:f}", object_.rotation_euler[0]) - roty = self.__write_rotation( + roty = self._write_rotation( "Y", "0 1 0 {:f}", object_.rotation_euler[1]) - rotz = self.__write_rotation( + rotz = self._write_rotation( "Z", "0 0 1 {:f}", object_.rotation_euler[2]) return rotx, roty, rotz - def __write_rotation(self, axis, textFormat, rotation): - rot = self.__doc.createElement("rotate") + def _write_rotation(self, axis, textFormat, rotation): + rot = self._doc.createElement("rotate") rot.setAttribute("sid", "rotation_{}".format(axis)) - rot_text = self.__doc.createTextNode(textFormat.format( + rot_text = self._doc.createTextNode(textFormat.format( rotation * utils.to_degrees)) rot.appendChild(rot_text) return rot - def __create_scale_node(self, object_): - scale = self.__doc.createElement("scale") + def _create_scale_node(self, object_): + scale = self._doc.createElement("scale") scale.setAttribute("sid", "scale") - scale_text = self.__doc.createTextNode( + scale_text = self._doc.createTextNode( utils.floats_to_string(object_.scale, " ", "%s")) scale.appendChild(scale_text) return scale - def __create_instance(self, object_): + def _create_instance(self, object_): armature = utils.get_armature_for_object(object_) instance = None if armature is not None: - instance = self.__doc.createElement("instance_controller") + instance = self._doc.createElement("instance_controller") # This binds the mesh object to the armature in control of it instance.setAttribute("url", "#{!s}_{!s}".format( armature.name, object_.name)) elif object_.name[:6] != "_joint" and object_.type == "MESH": - instance = self.__doc.createElement("instance_geometry") + instance = self._doc.createElement("instance_geometry") instance.setAttribute("url", "#{!s}".format(object_.name)) if instance is not None: - bind_material = self.__create_bind_material(object_) + bind_material = self._create_bind_material(object_) instance.appendChild(bind_material) return instance - def __create_bind_material(self, object_): - bind_material = self.__doc.createElement('bind_material') - technique_common = self.__doc.createElement('technique_common') + def _create_bind_material(self, object_): + bind_material = self._doc.createElement('bind_material') + technique_common = self._doc.createElement('technique_common') - for material, materialname in self.__get_materials_for_object( + for material, materialname in self._get_materials_for_object( object_).items(): - instance_material = self.__doc.createElement( + instance_material = self._doc.createElement( 'instance_material') instance_material.setAttribute('symbol', materialname) instance_material.setAttribute('target', '#{!s}'.format( materialname)) - bind_vertex_input = self.__doc.createElement( + bind_vertex_input = self._doc.createElement( 'bind_vertex_input') bind_vertex_input.setAttribute('semantic', 'UVMap') bind_vertex_input.setAttribute('input_semantic', 'TEXCOORD') @@ -1277,80 +1277,80 @@ def __create_bind_material(self, object_): return bind_material - def __create_cryengine_extra(self, node): - extra = self.__doc.createElement("extra") - technique = self.__doc.createElement("technique") + def _create_cryengine_extra(self, node): + extra = self._doc.createElement("extra") + technique = self._doc.createElement("technique") technique.setAttribute("profile", "CryEngine") - properties = self.__doc.createElement("properties") + properties = self._doc.createElement("properties") ALLOWED_NODE_TYPES = ("cgf", "cga", "chr", "skin", "anm", "i_caf") if utils.is_export_node(node): node_type = utils.get_node_type(node) if node_type in ALLOWED_NODE_TYPES: - prop = self.__doc.createTextNode( + prop = self._doc.createTextNode( "fileType={}".format(node_type)) properties.appendChild(prop) - if self.__config.do_not_merge: - prop = self.__doc.createTextNode("DoNotMerge") + if self._config.do_not_merge: + prop = self._doc.createTextNode("DoNotMerge") properties.appendChild(prop) else: if not node.rna_type.id_data.items(): return for prop in node.rna_type.id_data.items(): - self.__create_user_defined_property(prop, properties) + self._create_user_defined_property(prop, properties) technique.appendChild(properties) if (node.name[:6] == "_joint"): - helper = self.__create_helper_joint(node) + helper = self._create_helper_joint(node) technique.appendChild(helper) extra.appendChild(technique) return extra - def __create_user_defined_property(self, prop, node): + def _create_user_defined_property(self, prop, node): if prop: prop_name = prop[0] if add.is_user_defined_property(prop_name): udp = None if isinstance(prop[1], str): - udp = self.__doc.createTextNode("{!s}".format(prop[1])) + udp = self._doc.createTextNode("{!s}".format(prop[1])) else: - udp = self.__doc.createTextNode("{!s}=".format(prop[0]) + udp = self._doc.createTextNode("{!s}=".format(prop[0]) + "{!s}".format(prop[1])) node.appendChild(udp) - def __create_helper_joint(self, object_): + def _create_helper_joint(self, object_): x1, y1, z1, x2, y2, z2 = utils.get_bounding_box(object_) - min = self.__doc.createElement("bound_box_min") - min_text = self.__doc.createTextNode( + min = self._doc.createElement("bound_box_min") + min_text = self._doc.createTextNode( "{:f} {:f} {:f}".format(x1, y1, z1)) min.appendChild(min_text) - max = self.__doc.createElement("bound_box_max") - max_text = self.__doc.createTextNode( + max = self._doc.createElement("bound_box_max") + max_text = self._doc.createTextNode( "{:f} {:f} {:f}".format(x2, y2, z2)) max.appendChild(max_text) - joint = self.__doc.createElement("helper") + joint = self._doc.createElement("helper") joint.setAttribute("type", "dummy") joint.appendChild(min) joint.appendChild(max) return joint - def __create_props_bone_name(self, bone, node_name): + def _create_props_bone_name(self, bone, node_name): bone_name = bone.name.replace("__", "*") props_name = '%{!s}%--PRprops_name={!s}'.format(node_name, bone_name) return props_name - def __create_ik_properties(self, bone, object_): + def _create_ik_properties(self, bone, object_): props = "" if utils.is_physical(bone): @@ -1381,9 +1381,9 @@ def __create_ik_properties(self, bone, object_): return props - def __export_scene(self, parent_element): - scene = self.__doc.createElement("scene") - instance_visual_scene = self.__doc.createElement( + def _export_scene(self, parent_element): + scene = self._doc.createElement("scene") + instance_visual_scene = self._doc.createElement( "instance_visual_scene") instance_visual_scene.setAttribute("url", "#scene") scene.appendChild(instance_visual_scene) @@ -1398,7 +1398,7 @@ def write_scripts(config): dae_path = utils.get_absolute_path_for_rc(filepath) output_path = os.path.dirname(dae_path) chr_names = [] - for group in utils.get_export_nodes(self.__config.export_selected_nodes): + for group in utils.get_export_nodes(self._config.export_selected_nodes): if utils.get_node_type(group) == "chr": chr_names.append(utils.get_node_name(group)) From 5760455d1fa3e6b2c950f64ff6fd8a6c762f7365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Tue, 14 Jun 2016 13:22:38 +0300 Subject: [PATCH 04/17] Export Multiple Animation #201 --- io_export_cryblend/__init__.py | 195 ++++++++++++- io_export_cryblend/exceptions.py | 8 + io_export_cryblend/export.py | 224 +-------------- io_export_cryblend/export_animations.py | 352 ++++++++++++++++++++++++ io_export_cryblend/utils.py | 46 +++- 5 files changed, 601 insertions(+), 224 deletions(-) create mode 100644 io_export_cryblend/export_animations.py diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index 9190064..270311c 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -59,7 +59,7 @@ imp.reload(desc) else: import bpy - from io_export_cryblend import add, export, exceptions, utils, desc + from io_export_cryblend import add, export, export_animations, exceptions, utils, desc from bpy.props import BoolProperty, EnumProperty, FloatVectorProperty, \ FloatProperty, IntProperty, StringProperty, BoolVectorProperty @@ -235,6 +235,75 @@ def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self) +class AddCryAnimationNode(bpy.types.Operator): + '''Add selected objects to an existing or new CryExportNode''' + bl_label = "Add Animation Node" + bl_idname = "object.add_cry_animation_node" + bl_options = {"REGISTER", "UNDO"} + + node_name = StringProperty(name="Animation Name") + node_start = IntProperty(name="Start Frame") + node_end = IntProperty(name="End Frame") + is_use_markers = BoolProperty(name="Use Markers") + start_m_name = StringProperty(name="Marker Start Name") + end_m_name = StringProperty(name="Marker End Name") + + def __init__(self): + self.node_start = bpy.context.scene.frame_start + self.node_end = bpy.context.scene.frame_end + + return None + + def execute(self, context): + skeleton = bpy.context.active_object + if skeleton and skeleton.type == 'ARMATURE': + node_start = None + node_end = None + + start_name = "{}_Start".format(self.node_name) + end_name = "{}_End".format(self.node_name) + + if self.is_use_markers: + node_start = self.start_m_name + node_end = self.end_m_name + + tm = bpy.context.scene.timeline_markers + if tm.find(self.start_m_name) == -1: + tm.new(name=self.start_m_name, frame=self.node_start) + if tm.find(self.end_m_name) == -1: + tm.new(name=self.end_m_name, frame=self.node_end) + else: + node_start = self.node_start + node_end = self.node_end + + skeleton[start_name] = node_start + skeleton[end_name] = node_end + + node_name = "{}.i_caf".format(self.node_name) + group = bpy.data.groups.get(node_name) + if group is None: + bpy.ops.group.create(name=node_name) + else: + for object in bpy.context.selected_objects: + if object.name not in group.objects: + group.objects.link(object) + + message = "Adding Export Node" + else: + message = "There is no a active armature! Please select a armature." + + self.report({"INFO"}, message) + return {"FINISHED"} + + def invoke(self, context, event): + skeleton = bpy.context.active_object + if not skeleton or skeleton.type != 'ARMATURE': + self.report({'ERROR'}, "Please select and active a armature.") + return {'FINISHED'} + + return context.window_manager.invoke_props_dialog(self) + + class SelectedToCryExportNodes(bpy.types.Operator): '''Add selected objects to individual CryExportNodes.''' bl_label = "Nodes from Object Names" @@ -1952,6 +2021,114 @@ def draw(self, context): box.prop(self, "run_in_profiler") +class ExportAnimations(bpy.types.Operator, ExportHelper): + '''Export animations to CryEngine''' + bl_label = "Export Animations" + bl_idname = "scene.export_animations" + filename_ext = ".dae" + filter_glob = StringProperty(default="*.dae", options={'HIDDEN'}) + + do_not_merge = BoolProperty( + name="Do Not Merge Nodes", + description="Generally a good idea.", + default=True, + ) + export_for_lumberyard = BoolProperty( + name="Export for LumberYard", + description="Export for LumberYard engine instead of CryEngine.", + default=False, + ) + disable_rc = BoolProperty( + name="Disable RC", + description="Do not run the resource compiler.", + default=False, + ) + save_dae = BoolProperty( + name="Save DAE File", + description="Save the DAE file for developing purposes.", + default=False, + ) + run_in_profiler = BoolProperty( + name="Profile CryBlend", + description="Select only if you want to profile CryBlend.", + default=False, + ) + do_materials = False + make_layer = False + + class Config: + + def __init__(self, config): + attributes = ( + 'filepath', + 'do_not_merge', + 'do_materials', + 'export_for_lumberyard', + 'make_layer', + 'disable_rc', + 'save_dae', + 'run_in_profiler' + ) + + for attribute in attributes: + setattr(self, attribute, getattr(config, attribute)) + + setattr(self, 'cryblend_version', VERSION) + setattr(self, 'rc_path', Configuration.rc_path) + setattr(self, 'texture_rc_path', Configuration.texture_rc_path) + setattr(self, 'game_dir', Configuration.game_dir) + + def execute(self, context): + cbPrint(Configuration.rc_path, 'debug') + try: + config = ExportAnimations.Config(config=self) + + if self.run_in_profiler: + import cProfile + cProfile.runctx('export_animations.save(config)', {}, + {'export_animations': export_animations, 'config': config}) + else: + export_animations.save(config) + + self.filepath = '//' + + except exceptions.CryBlendException as exception: + cbPrint(exception.what(), 'error') + bpy.ops.screen.display_error( + 'INVOKE_DEFAULT', message=exception.what()) + + return {'FINISHED'} + + def invoke(self, context, event): + if not Configuration.configured(): + self.report({'ERROR'}, "No RC found.") + return {'FINISHED'} + + if not utils.get_export_nodes(): + self.report({'ERROR'}, "No export nodes found.") + return {'FINISHED'} + + return ExportHelper.invoke(self, context, event) + + def draw(self, context): + layout = self.layout + col = layout.column() + + box = col.box() + box.label("General", icon="WORLD") + box.prop(self, "do_not_merge") + + box = col.box() + box.label("LumberYard", icon="GAME") + box.prop(self, "export_for_lumberyard") + + box = col.box() + box.label("Developer Tools", icon="MODIFIER") + box.prop(self, "disable_rc") + box.prop(self, "save_dae") + box.prop(self, "run_in_profiler") + + class ErrorHandler(bpy.types.Operator): bl_label = "Error:" bl_idname = "screen.display_error" @@ -2013,6 +2190,7 @@ def draw(self, context): col.separator() row = col.row(align=True) row.operator("object.add_cry_export_node", text="Add Export Node") + row.operator("object.add_cry_animation_node", text="Add Animation Node") col.operator( "object.selected_to_cry_export_nodes", text="Export Nodes from Objects") @@ -2166,6 +2344,10 @@ def draw(self, context): col.label("Export", icon="GAME") col.separator() col.operator("scene.export_to_game", text="Export to Game") + col.separator() + col.label("Export Animations", icon="GAME") + col.separator() + col.operator("scene.export_animations", text="Export Animations") #------------------------------------------------------------------------------ # CryBlend Menu: @@ -2190,9 +2372,14 @@ def draw(self, context): "object.add_cry_export_node", text="Add Export Node", icon="GROUP") + layout.operator( + "object.add_cry_animation_node", + text="Add Animation Node", + icon="PREVIEW_RANGE") layout.operator( "object.selected_to_cry_export_nodes", - text="Export Nodes from Objects") + text="Export Nodes from Objects", + icon="GROUP") layout.separator() layout.operator( "object.apply_transforms", @@ -2217,6 +2404,8 @@ def draw(self, context): layout.separator() layout.separator() layout.operator("scene.export_to_game", icon="GAME") + layout.separator() + layout.operator("scene.export_animations", icon="RENDER_ANIMATION") class AddPhysicsProxyMenu(bpy.types.Menu): @@ -2518,6 +2707,7 @@ def get_classes_to_register(): SaveCryBlendConfiguration, AddCryExportNode, + AddCryAnimationNode, SelectedToCryExportNodes, AddMaterial, SetMaterialNames, @@ -2558,6 +2748,7 @@ def get_classes_to_register(): ApplyAnimationScale, Export, + ExportAnimations, ErrorHandler, ExportUtilitiesPanel, diff --git a/io_export_cryblend/exceptions.py b/io_export_cryblend/exceptions.py index ec56f4b..4c0b496 100644 --- a/io_export_cryblend/exceptions.py +++ b/io_export_cryblend/exceptions.py @@ -63,3 +63,11 @@ def __init__(self): message = "Please select a Game Directory!" CryBlendException.__init__(self, message) + + +class MarkersNotFound(CryBlendException): + + def __init__(self): + message = "Start or end marker is less!" + + CryBlendException.__init__(self, message) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index a07719b..3b730e9 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -40,13 +40,6 @@ import xml.dom.minidom -AXES = { - 'X': 0, - 'Y': 1, - 'Z': 2, -} - - class CrytekDaeExporter: def __init__(self, config): @@ -802,7 +795,7 @@ def _process_bone_weights(self, object_, armature, skin_node): skin_node.appendChild(vertex_weights) # ----------------------------------------------------------------------------- -# Library Animation and Clips: --> Animations, Fakebones, Bone Geometries +# Library Animation and Clips: --> Animations, F-Curves # ----------------------------------------------------------------------------- def _export_library_animation_clips_and_animations(self, parent_element): @@ -811,213 +804,6 @@ def _export_library_animation_clips_and_animations(self, parent_element): parent_element.appendChild(libanmcl) parent_element.appendChild(libanm) - scene = bpy.context.scene - - ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") - for group in utils.get_export_nodes( - self._config.export_selected_nodes): - node_type = utils.get_node_type(group) - if node_type in ALLOWED_NODE_TYPES: - animation_clip = self._doc.createElement("animation_clip") - node_name = utils.get_node_name(group) - animation_clip.setAttribute( - "id", "{!s}-{!s}".format(node_name, node_name)) - animation_clip.setAttribute( - "start", "{:f}".format( - utils.frame_to_time( - scene.frame_start))) - animation_clip.setAttribute( - "end", "{:f}".format( - utils.frame_to_time( - scene.frame_end))) - is_animation = False - - for object_ in bpy.context.selected_objects: - if (object_.type != 'ARMATURE' and object_.animation_data and - object_.animation_data.action): - - is_animation = True - - props_name = self._create_props_bone_name( - object_, node_name) - bone_name = "{!s}{!s}".format(object_.name, props_name) - - for axis in iter(AXES): - animation = self._get_animation_location( - object_, bone_name, axis, node_name) - if animation is not None: - libanm.appendChild(animation) - - for axis in iter(AXES): - animation = self._get_animation_rotation( - object_, bone_name, axis, node_name) - if animation is not None: - libanm.appendChild(animation) - - self._export_instance_animation_parameters( - object_, animation_clip, node_name) - - if is_animation: - libanmcl.appendChild(animation_clip) - - def _export_instance_animation_parameters(self, object_, animation_clip, node_name): - location_exists = rotation_exists = False - for curve in object_.animation_data.action.fcurves: - for axis in iter(AXES): - if curve.array_index == AXES[axis]: - if curve.data_path == "location": - location_exists = True - if curve.data_path == "rotation_euler": - rotation_exists = True - if location_exists and rotation_exists: - break - - if location_exists: - self._export_instance_parameter( - object_, animation_clip, "location", node_name) - if rotation_exists: - self._export_instance_parameter( - object_, animation_clip, "rotation_euler", node_name) - - def _export_instance_parameter(self, object_, animation_clip, parameter, node_name): - for axis in iter(AXES): - inst = self._doc.createElement("instance_animation") - inst.setAttribute( - "url", "#{!s}-{!s}-{!s}_{!s}_{!s}".format( - node_name, node_name, object_.name, parameter, axis)) - animation_clip.appendChild(inst) - - def _get_animation_location(self, object_, bone_name, axis, node_name): - attribute_type = "location" - multiplier = 1 - target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) - - animation_element = self._get_animation_attribute(object_, - axis, - attribute_type, - multiplier, - target, - node_name) - return animation_element - - def _get_animation_rotation(self, object_, bone_name, axis, node_name): - attribute_type = "rotation_euler" - multiplier = utils.to_degrees - target = "{!s}{!s}{!s}{!s}".format(bone_name, - "/rotation_", - axis, - ".ANGLE") - - animation_element = self._get_animation_attribute(object_, - axis, - attribute_type, - multiplier, - target, - node_name) - return animation_element - - def _get_animation_attribute(self, - object_, - axis, - attribute_type, - multiplier, - target, - node_name): - id_prefix = "{!s}-{!s}-{!s}_{!s}_{!s}".format(node_name, node_name, - object_.name, attribute_type, axis) - source_prefix = "#{!s}".format(id_prefix) - - for curve in object_.animation_data.action.fcurves: - if (curve.data_path == - attribute_type and curve.array_index == AXES[axis]): - keyframe_points = curve.keyframe_points - sources = { - "input": [], - "output": [], - "interpolation": [], - "intangent": [], - "outangent": [] - } - for keyframe_point in keyframe_points: - khlx = keyframe_point.handle_left[0] - khly = keyframe_point.handle_left[1] - khrx = keyframe_point.handle_right[0] - khry = keyframe_point.handle_right[1] - frame, value = keyframe_point.co - - sources["input"].append(utils.frame_to_time(frame)) - sources["output"].append(value * multiplier) - sources["interpolation"].append( - keyframe_point.interpolation) - sources["intangent"].extend( - [utils.frame_to_time(khlx), khly]) - sources["outangent"].extend( - [utils.frame_to_time(khrx), khry]) - - animation_element = self._doc.createElement("animation") - animation_element.setAttribute("id", id_prefix) - - for type_, data in sources.items(): - anim_node = self._create_animation_node( - type_, data, id_prefix) - animation_element.appendChild(anim_node) - - sampler = self._create_sampler(id_prefix, source_prefix) - channel = self._doc.createElement("channel") - channel.setAttribute( - "source", "{!s}-sampler".format(source_prefix)) - channel.setAttribute("target", target) - - animation_element.appendChild(sampler) - animation_element.appendChild(channel) - - return animation_element - - def _create_animation_node(self, type_, data, id_prefix): - id_ = "{!s}-{!s}".format(id_prefix, type_) - type_map = { - "input": ["float", ["TIME"]], - "output": ["float", ["VALUE"]], - "intangent": ["float", "XY"], - "outangent": ["float", "XY"], - "interpolation": ["name", ["INTERPOLATION"]] - } - - source = utils.write_source( - id_, type_map[type_][0], data, type_map[type_][1]) - - return source - - def _create_sampler(self, id_prefix, source_prefix): - sampler = self._doc.createElement("sampler") - sampler.setAttribute("id", "{!s}-sampler".format(id_prefix)) - - input = self._doc.createElement("input") - input.setAttribute("semantic", "INPUT") - input.setAttribute("source", "{!s}-input".format(source_prefix)) - output = self._doc.createElement("input") - output.setAttribute("semantic", "OUTPUT") - output.setAttribute("source", "{!s}-output".format(source_prefix)) - interpolation = self._doc.createElement("input") - interpolation.setAttribute("semantic", "INTERPOLATION") - interpolation.setAttribute( - "source", "{!s}-interpolation".format(source_prefix)) - intangent = self._doc.createElement("input") - intangent.setAttribute("semantic", "IN_TANGENT") - intangent.setAttribute( - "source", "{!s}-intangent".format(source_prefix)) - outangent = self._doc.createElement("input") - outangent.setAttribute("semantic", "OUT_TANGENT") - outangent.setAttribute( - "source", "{!s}-outangent".format(source_prefix)) - - sampler.appendChild(input) - sampler.appendChild(output) - sampler.appendChild(interpolation) - sampler.appendChild(intangent) - sampler.appendChild(outangent) - - return sampler # --------------------------------------------------------------------- # Library Visual Scene: --> Skeleton and _Phys bones, Bone @@ -1080,9 +866,11 @@ def _write_visual_scene_node(self, objects, parent_node, group): self._write_transforms(object_, node) - instance = self._create_instance(object_) - if instance is not None: - node.appendChild(instance) + ALLOWED_NODE_TYPES = ('cgf', 'cga', 'chr', 'skin') + if utils.get_node_type(group) in ALLOWED_NODE_TYPES: + instance = self._create_instance(object_) + if instance is not None: + node.appendChild(instance) extra = self._create_cryengine_extra(object_) if extra is not None: diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py new file mode 100644 index 0000000..1b46b0f --- /dev/null +++ b/io_export_cryblend/export_animations.py @@ -0,0 +1,352 @@ +#------------------------------------------------------------------------------ +# Name: export_animations.py +# Purpose: Animation exporter to CryEngine +# +# Author: Özkan Afacan, +# Angelo J. Miner, Daniel White, David Marcelis, Duo Oratar, +# Mikołaj Milej, Oscar Martin Garcia +# +# Created: 13/06/2016 +# Copyright: (c) Özkan Afacan 2016 +# License: GPLv2+ +#------------------------------------------------------------------------------ + + +if "bpy" in locals(): + import imp + imp.reload(utils) + imp.reload(exceptions) +else: + import bpy + from io_export_cryblend import export, utils, add, exceptions + +from io_export_cryblend.rc import RCInstance +from io_export_cryblend.outpipe import cbPrint + +from xml.dom.minidom import Document, Element, parse, parseString +import xml.dom.minidom +import os + + +AXES = { + 'X': 0, + 'Y': 1, + 'Z': 2, +} + + +class CrytekDaeAnimationExporter(export.CrytekDaeExporter): + + def __init__(self, config): + self._config = config + self._doc = Document() + + def export(self): + self._prepare_for_export() + + root_element = self._doc.createElement('collada') + root_element.setAttribute( + "xmlns", "http://www.collada.org/2005/11/COLLADASchema") + root_element.setAttribute("version", "1.4.1") + self._doc.appendChild(root_element) + self._create_file_header(root_element) + + libanmcl = self._doc.createElement("library_animation_clips") + libanm = self._doc.createElement("library_animations") + root_element.appendChild(libanmcl) + root_element.appendChild(libanm) + + lib_visual_scene = self._doc.createElement("library_visual_scenes") + visual_scene = self._doc.createElement("visual_scene") + visual_scene.setAttribute("id", "scene") + visual_scene.setAttribute("name", "scene") + lib_visual_scene.appendChild(visual_scene) + root_element.appendChild(lib_visual_scene) + + ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") + for group in utils.get_export_nodes(): + + node_type = utils.get_node_type(group) + node_name = utils.get_node_name(group) + + object_ = None + + if node_type == 'i_caf': + object_ = utils.get_armature_from_node(group) + elif node_type == 'anm': + object_ = group.objects[0] + + frame_start, frame_end = utils.get_animation_node_range(object_, node_name) + bpy.context.scene.frame_start = frame_start + bpy.context.scene.frame_end = frame_end + + if node_type == 'i_caf': + utils.add_fakebones(group) + try: + self._export_library_animation_clips_and_animations(libanmcl, libanm, group) + self._export_library_visual_scenes(visual_scene, group) + except RuntimeError: + pass + finally: + if node_type == 'i_caf': + utils.remove_fakebones() + + self._export_scene(root_element) + + converter = RCInstance(self._config) + converter.convert_dae(self._doc) + + def _prepare_for_export(self): + utils.clean_file() + + +# ----------------------------------------------------------------------------- +# Library Animations and Clips: --> Animations, F-Curves +# ----------------------------------------------------------------------------- + + def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group): + + scene = bpy.context.scene + + animation_clip = self._doc.createElement("animation_clip") + node_name = utils.get_node_name(group) + animation_clip.setAttribute("id", "{!s}-{!s}".format(node_name, node_name)) + animation_clip.setAttribute("start", "{:f}".format( + utils.frame_to_time(scene.frame_start))) + animation_clip.setAttribute("end", "{:f}".format( + utils.frame_to_time(scene.frame_end))) + is_animation = False + + for object_ in bpy.context.selected_objects: + if (object_.type != 'ARMATURE' and object_.animation_data and + object_.animation_data.action): + + is_animation = True + + props_name = self._create_props_bone_name(object_, node_name) + bone_name = "{!s}{!s}".format(object_.name, props_name) + + for axis in iter(AXES): + animation = self._get_animation_location( + object_, bone_name, axis, node_name) + if animation is not None: + libanm.appendChild(animation) + + for axis in iter(AXES): + animation = self._get_animation_rotation( + object_, bone_name, axis, node_name) + if animation is not None: + libanm.appendChild(animation) + + self._export_instance_animation_parameters( + object_, animation_clip, node_name) + + if is_animation: + libanmcl.appendChild(animation_clip) + + def _export_instance_animation_parameters(self, object_, animation_clip, node_name): + location_exists = rotation_exists = False + for curve in object_.animation_data.action.fcurves: + for axis in iter(AXES): + if curve.array_index == AXES[axis]: + if curve.data_path == "location": + location_exists = True + if curve.data_path == "rotation_euler": + rotation_exists = True + if location_exists and rotation_exists: + break + + if location_exists: + self._export_instance_parameter( + object_, animation_clip, "location", node_name) + if rotation_exists: + self._export_instance_parameter( + object_, animation_clip, "rotation_euler", node_name) + + def _export_instance_parameter(self, object_, animation_clip, parameter, node_name): + for axis in iter(AXES): + inst = self._doc.createElement("instance_animation") + inst.setAttribute( + "url", "#{!s}-{!s}-{!s}_{!s}_{!s}".format( + node_name, node_name, object_.name, parameter, axis)) + animation_clip.appendChild(inst) + + def _get_animation_location(self, object_, bone_name, axis, node_name): + attribute_type = "location" + multiplier = 1 + target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) + + animation_element = self._get_animation_attribute(object_, + axis, + attribute_type, + multiplier, + target, + node_name) + return animation_element + + def _get_animation_rotation(self, object_, bone_name, axis, node_name): + attribute_type = "rotation_euler" + multiplier = utils.to_degrees + target = "{!s}{!s}{!s}{!s}".format(bone_name, + "/rotation_", + axis, + ".ANGLE") + + animation_element = self._get_animation_attribute(object_, + axis, + attribute_type, + multiplier, + target, + node_name) + return animation_element + + def _get_animation_attribute(self, + object_, + axis, + attribute_type, + multiplier, + target, + node_name): + id_prefix = "{!s}-{!s}-{!s}_{!s}_{!s}".format(node_name, node_name, + object_.name, attribute_type, axis) + source_prefix = "#{!s}".format(id_prefix) + + for curve in object_.animation_data.action.fcurves: + if (curve.data_path == + attribute_type and curve.array_index == AXES[axis]): + keyframe_points = curve.keyframe_points + sources = { + "input": [], + "output": [], + "interpolation": [], + "intangent": [], + "outangent": [] + } + for keyframe_point in keyframe_points: + khlx = keyframe_point.handle_left[0] + khly = keyframe_point.handle_left[1] + khrx = keyframe_point.handle_right[0] + khry = keyframe_point.handle_right[1] + frame, value = keyframe_point.co + + sources["input"].append(utils.frame_to_time(frame)) + sources["output"].append(value * multiplier) + sources["interpolation"].append( + keyframe_point.interpolation) + sources["intangent"].extend( + [utils.frame_to_time(khlx), khly]) + sources["outangent"].extend( + [utils.frame_to_time(khrx), khry]) + + animation_element = self._doc.createElement("animation") + animation_element.setAttribute("id", id_prefix) + + for type_, data in sources.items(): + anim_node = self._create_animation_node( + type_, data, id_prefix) + animation_element.appendChild(anim_node) + + sampler = self._create_sampler(id_prefix, source_prefix) + channel = self._doc.createElement("channel") + channel.setAttribute( + "source", "{!s}-sampler".format(source_prefix)) + channel.setAttribute("target", target) + + animation_element.appendChild(sampler) + animation_element.appendChild(channel) + + return animation_element + + def _create_animation_node(self, type_, data, id_prefix): + id_ = "{!s}-{!s}".format(id_prefix, type_) + type_map = { + "input": ["float", ["TIME"]], + "output": ["float", ["VALUE"]], + "intangent": ["float", "XY"], + "outangent": ["float", "XY"], + "interpolation": ["name", ["INTERPOLATION"]] + } + + source = utils.write_source( + id_, type_map[type_][0], data, type_map[type_][1]) + + return source + + def _create_sampler(self, id_prefix, source_prefix): + sampler = self._doc.createElement("sampler") + sampler.setAttribute("id", "{!s}-sampler".format(id_prefix)) + + input = self._doc.createElement("input") + input.setAttribute("semantic", "INPUT") + input.setAttribute("source", "{!s}-input".format(source_prefix)) + output = self._doc.createElement("input") + output.setAttribute("semantic", "OUTPUT") + output.setAttribute("source", "{!s}-output".format(source_prefix)) + interpolation = self._doc.createElement("input") + interpolation.setAttribute("semantic", "INTERPOLATION") + interpolation.setAttribute( + "source", "{!s}-interpolation".format(source_prefix)) + intangent = self._doc.createElement("input") + intangent.setAttribute("semantic", "IN_TANGENT") + intangent.setAttribute( + "source", "{!s}-intangent".format(source_prefix)) + outangent = self._doc.createElement("input") + outangent.setAttribute("semantic", "OUT_TANGENT") + outangent.setAttribute( + "source", "{!s}-outangent".format(source_prefix)) + + sampler.appendChild(input) + sampler.appendChild(output) + sampler.appendChild(interpolation) + sampler.appendChild(intangent) + sampler.appendChild(outangent) + + return sampler + +# --------------------------------------------------------------------- +# Library Visual Scene: --> Skeleton and _Phys bones, Bone +# Transformations, and Instance URL (_boneGeometry) and extras. +# --------------------------------------------------------------------- + + def _export_library_visual_scenes(self, visual_scene, group): + + if utils.get_export_nodes(): + if utils.are_duplicate_nodes(): + message = "Duplicate Node Names" + bpy.ops.screen.display_error('INVOKE_DEFAULT', message=message) + + self._write_export_node(group, visual_scene) + else: + pass # TODO: Handle No Export Nodes Error + + +# ------------------------------------------------------------------- + + +def save(config): + # prevent wasting time for exporting if RC was not found + if not config.disable_rc and not os.path.isfile(config.rc_path): + raise exceptions.NoRcSelectedException + + exporter = CrytekDaeAnimationExporter(config) + exporter.export() + + +def register(): + bpy.utils.register_class(CrytekDaeAnimationExporter) + + bpy.utils.register_class(TriangulateMeError) + bpy.utils.register_class(Error) + + +def unregister(): + bpy.utils.unregister_class(CrytekDaeAnimationExporter) + bpy.utils.unregister_class(TriangulateMeError) + bpy.utils.unregister_class(Error) + + +if __name__ == "__main__": + register() + + # test call + bpy.ops.export_mesh.crytekdae('INVOKE_DEFAULT') diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index c5cb263..c88760c 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -699,7 +699,7 @@ def is_fakebone(object_): return False -def add_fakebones(): +def add_fakebones(group = None): '''Add helpers to track bone transforms.''' scene = bpy.context.scene remove_unused_meshes() @@ -724,9 +724,8 @@ def add_fakebones(): armature.data.bones.active = pose_bone.bone bpy.ops.object.parent_set(type='BONE_RELATIVE') - ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") - - for group in armature.users_group: + if group: + ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") node_type = get_node_type(group) if node_type in ALLOWED_NODE_TYPES: @@ -993,6 +992,45 @@ def get_bones(armature): return [bone for bone in armature.data.bones] +def get_animation_node_range(object_, node_name): + try: + start_frame = object_["{}_Start".format(node_name)] + end_frame = object_["{}_End".format(node_name)] + + if type(start_frame) is str and type(end_frame) is str: + tm = bpy.context.scene.timeline_markers + if tm.find(start_frame) != -1 and tm.find(end_frame) != -1: + return tm[start_frame].frame, tm[end_frame].frame + else: + raise exceptions.MarkerNotFound + else: + return start_frame, end_frame + except: + return bpy.context.scene.frame_start, bpy.context.scene.frame_end + + +def get_armature_from_node(group): + armature_count = 0 + armature = None + for object_ in group.objects: + if object_.type == "ARMATURE": + armature_count += 1 + armature = object_ + + if armature_count == 1: + return armature + + error_message = None + if armature_count == 0: + raise exceptions.CryBlendException("i_caf node has no armature!") + error_message = "i_caf node has no armature!" + elif armature_count > 1: + raise exceptions.CryBlendException( + "{} i_caf node have more than one armature!".format(node_name)) + + return None + + #------------------------------------------------------------------------------ # General: #------------------------------------------------------------------------------ From be0b8bf3e054921d5d5db99af7160f515ea81e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Mon, 20 Jun 2016 23:30:48 +0300 Subject: [PATCH 05/17] Multiple animation improvements #201 --- io_export_cryblend/export_animations.py | 49 +++++++++++++------------ io_export_cryblend/utils.py | 11 ++---- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 1b46b0f..4c42590 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -62,34 +62,37 @@ def export(self): visual_scene.setAttribute("name", "scene") lib_visual_scene.appendChild(visual_scene) root_element.appendChild(lib_visual_scene) - - ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") + + ALLOWED_NODE_TYPES = ("i_caf", "anm") for group in utils.get_export_nodes(): node_type = utils.get_node_type(group) node_name = utils.get_node_name(group) - object_ = None - - if node_type == 'i_caf': - object_ = utils.get_armature_from_node(group) - elif node_type == 'anm': - object_ = group.objects[0] - - frame_start, frame_end = utils.get_animation_node_range(object_, node_name) - bpy.context.scene.frame_start = frame_start - bpy.context.scene.frame_end = frame_end - - if node_type == 'i_caf': - utils.add_fakebones(group) - try: - self._export_library_animation_clips_and_animations(libanmcl, libanm, group) - self._export_library_visual_scenes(visual_scene, group) - except RuntimeError: - pass - finally: + if node_type in ALLOWED_NODE_TYPES: + object_ = None + + if node_type == 'i_caf': + object_ = utils.get_armature_from_node(group) + elif node_type == 'anm': + object_ = group.objects[0] + + frame_start, frame_end = utils.get_animation_node_range( + object_, node_name) + bpy.context.scene.frame_start = frame_start + bpy.context.scene.frame_end = frame_end + if node_type == 'i_caf': - utils.remove_fakebones() + utils.add_fakebones(group) + try: + self._export_library_animation_clips_and_animations( + libanmcl, libanm, group) + self._export_library_visual_scenes(visual_scene, group) + except RuntimeError: + pass + finally: + if node_type == 'i_caf': + utils.remove_fakebones() self._export_scene(root_element) @@ -117,7 +120,7 @@ def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group utils.frame_to_time(scene.frame_end))) is_animation = False - for object_ in bpy.context.selected_objects: + for object_ in group.objects: if (object_.type != 'ARMATURE' and object_.animation_data and object_.animation_data.action): diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index c88760c..4170dfc 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -712,7 +712,6 @@ def add_fakebones(group = None): skeleton.pose_position = 'REST' time.sleep(0.5) - deselect_all() scene.frame_set(scene.frame_start) for pose_bone in armature.pose.bones: bmatrix = pose_bone.bone.head_local @@ -724,11 +723,11 @@ def add_fakebones(group = None): armature.data.bones.active = pose_bone.bone bpy.ops.object.parent_set(type='BONE_RELATIVE') - if group: - ALLOWED_NODE_TYPES = ("cga", "anm", "i_caf") - node_type = get_node_type(group) + if group: + group.objects.link(fakebone) - if node_type in ALLOWED_NODE_TYPES: + if group: + if get_node_type(group) == 'i_caf': process_animation(armature, skeleton) @@ -756,8 +755,6 @@ def process_animation(armature, skeleton): skeleton.pose_position = 'POSE' time.sleep(0.5) - select_all() - location_list, rotation_list = get_keyframes(armature) set_keyframes(armature, location_list, rotation_list) cbPrint("Animation was processed.") From fc1405bffba5b25242629b72a947b3b33bf76cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Tue, 14 Jun 2016 14:12:30 +0300 Subject: [PATCH 06/17] Create property name improvement #206 --- io_export_cryblend/export.py | 11 +++++------ io_export_cryblend/export_animations.py | 2 +- io_export_cryblend/utils.py | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index 3b730e9..e5a4450 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -713,10 +713,10 @@ def _process_bone_joints(self, object_, armature, skin_node): bones = utils.get_bones(armature) id_ = "{!s}_{!s}-joints".format(armature.name, object_.name) - node_name = utils.get_armature_node_name(object_) + group = utils.get_armature_node(object_) bone_names = [] for bone in bones: - props_name = self._create_props_bone_name(bone, node_name) + props_name = self._create_properties_name(bone, group) bone_name = "{!s}{!s}".format(bone.name, props_name) bone_names.append(bone_name) source = utils.write_source(id_, "IDREF", bone_names, []) @@ -892,10 +892,8 @@ def _write_bone_list(self, bones, object_, parent_node, group): scene = bpy.context.scene bone_names = [] - node_name = utils.get_node_name(group) - for bone in bones: - props_name = self._create_props_bone_name(bone, node_name) + props_name = self._create_properties_name(bone, group) props_ik = self._create_ik_properties(bone, object_) bone_name = join(bone.name, props_name, props_ik) bone_names.append(bone_name) @@ -1132,8 +1130,9 @@ def _create_helper_joint(self, object_): return joint - def _create_props_bone_name(self, bone, node_name): + def _create_properties_name(self, bone, group): bone_name = bone.name.replace("__", "*") + node_name = utils.get_node_name(group) props_name = '%{!s}%--PRprops_name={!s}'.format(node_name, bone_name) return props_name diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 4c42590..5e41f44 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -126,7 +126,7 @@ def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group is_animation = True - props_name = self._create_props_bone_name(object_, node_name) + props_name = self._create_properties_name(object_, group) bone_name = "{!s}{!s}".format(object_.name, props_name) for axis in iter(AXES): diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 4170dfc..6d08007 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -676,11 +676,11 @@ def get_node_type(node): return node_components[-1] -def get_armature_node_name(object_): +def get_armature_node(object_): ALLOWED_NODE_TYPES = ("cga", "anm", "chr", "skin", "i_caf") for group in object_.users_group: if get_node_type(group) in ALLOWED_NODE_TYPES: - return get_node_name(group) + return group #------------------------------------------------------------------------------ From ac564f0fc7bf756733cbbf2b9f69124672d0a5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Tue, 14 Jun 2016 16:32:06 +0300 Subject: [PATCH 07/17] Geometry Animation Fix #206 --- io_export_cryblend/export.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index e5a4450..7f017cf 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -860,8 +860,11 @@ def _write_export_node(self, group, visual_scene): def _write_visual_scene_node(self, objects, parent_node, group): for object_ in objects: if object_.type == "MESH" and not utils.is_fakebone(object_): + prop_name = join(object_.name, + self._create_properties_name(object_, group)) node = self._doc.createElement("node") - node.setAttribute("id", object_.name) + node.setAttribute("id", prop_name) + node.setAttribute("name", prop_name) node.setIdAttribute("id") self._write_transforms(object_, node) From e24a4393f29ef4e5375e1fd9f0874018c8d77cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Tue, 14 Jun 2016 17:45:42 +0300 Subject: [PATCH 08/17] Multiple Geometry Animation #206 --- io_export_cryblend/__init__.py | 35 +++++++++++------- io_export_cryblend/export_animations.py | 36 +++++++++---------- io_export_cryblend/rc.py | 19 ++++++++++ io_export_cryblend/utils.py | 47 +++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 30 deletions(-) diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index 270311c..bbcca49 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -198,10 +198,6 @@ class AddCryExportNode(bpy.types.Operator): "Character"), ("skin", "SKIN", "Skinned Render Mesh"), - ("anm", "ANM", - "Geometry Animation"), - ("i_caf", "I_CAF", - "Character Animation"), ), default="cgf", ) @@ -241,6 +237,16 @@ class AddCryAnimationNode(bpy.types.Operator): bl_idname = "object.add_cry_animation_node" bl_options = {"REGISTER", "UNDO"} + node_type = EnumProperty( + name="Type", + items=( + ("anm", "ANM", + "Geometry Animation"), + ("i_caf", "I_CAF", + "Character Animation"), + ), + default="i_caf", + ) node_name = StringProperty(name="Animation Name") node_start = IntProperty(name="Start Frame") node_end = IntProperty(name="End Frame") @@ -251,12 +257,17 @@ class AddCryAnimationNode(bpy.types.Operator): def __init__(self): self.node_start = bpy.context.scene.frame_start self.node_end = bpy.context.scene.frame_end + + if bpy.context.active_object.type == 'ARMATURE': + self.node_type = 'i_caf' + else: + self.node_type = 'anm' return None def execute(self, context): - skeleton = bpy.context.active_object - if skeleton and skeleton.type == 'ARMATURE': + object_ = bpy.context.active_object + if object_: node_start = None node_end = None @@ -276,10 +287,10 @@ def execute(self, context): node_start = self.node_start node_end = self.node_end - skeleton[start_name] = node_start - skeleton[end_name] = node_end + object_[start_name] = node_start + object_[end_name] = node_end - node_name = "{}.i_caf".format(self.node_name) + node_name = "{}.{}".format(self.node_name, self.node_type) group = bpy.data.groups.get(node_name) if group is None: bpy.ops.group.create(name=node_name) @@ -296,9 +307,9 @@ def execute(self, context): return {"FINISHED"} def invoke(self, context, event): - skeleton = bpy.context.active_object - if not skeleton or skeleton.type != 'ARMATURE': - self.report({'ERROR'}, "Please select and active a armature.") + object_ = bpy.context.active_object + if not object_: + self.report({'ERROR'}, "Please select and active a armature or object.") return {'FINISHED'} return context.window_manager.invoke_props_dialog(self) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 5e41f44..d118968 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -110,10 +110,10 @@ def _prepare_for_export(self): def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group): scene = bpy.context.scene + anim_id = utils.get_animation_id(group) animation_clip = self._doc.createElement("animation_clip") - node_name = utils.get_node_name(group) - animation_clip.setAttribute("id", "{!s}-{!s}".format(node_name, node_name)) + animation_clip.setAttribute("id", anim_id) animation_clip.setAttribute("start", "{:f}".format( utils.frame_to_time(scene.frame_start))) animation_clip.setAttribute("end", "{:f}".format( @@ -131,23 +131,23 @@ def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group for axis in iter(AXES): animation = self._get_animation_location( - object_, bone_name, axis, node_name) + object_, bone_name, axis, anim_id) if animation is not None: libanm.appendChild(animation) for axis in iter(AXES): animation = self._get_animation_rotation( - object_, bone_name, axis, node_name) + object_, bone_name, axis, anim_id) if animation is not None: libanm.appendChild(animation) self._export_instance_animation_parameters( - object_, animation_clip, node_name) + object_, animation_clip, anim_id) if is_animation: libanmcl.appendChild(animation_clip) - def _export_instance_animation_parameters(self, object_, animation_clip, node_name): + def _export_instance_animation_parameters(self, object_, animation_clip, anim_id): location_exists = rotation_exists = False for curve in object_.animation_data.action.fcurves: for axis in iter(AXES): @@ -161,20 +161,20 @@ def _export_instance_animation_parameters(self, object_, animation_clip, node_na if location_exists: self._export_instance_parameter( - object_, animation_clip, "location", node_name) + object_, animation_clip, "location", anim_id) if rotation_exists: self._export_instance_parameter( - object_, animation_clip, "rotation_euler", node_name) + object_, animation_clip, "rotation_euler", anim_id) - def _export_instance_parameter(self, object_, animation_clip, parameter, node_name): + def _export_instance_parameter(self, object_, animation_clip, parameter, anim_id): for axis in iter(AXES): inst = self._doc.createElement("instance_animation") inst.setAttribute( - "url", "#{!s}-{!s}-{!s}_{!s}_{!s}".format( - node_name, node_name, object_.name, parameter, axis)) + "url", "#{!s}-{!s}_{!s}_{!s}".format( + anim_id, object_.name, parameter, axis)) animation_clip.appendChild(inst) - def _get_animation_location(self, object_, bone_name, axis, node_name): + def _get_animation_location(self, object_, bone_name, axis, anim_id): attribute_type = "location" multiplier = 1 target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) @@ -184,10 +184,10 @@ def _get_animation_location(self, object_, bone_name, axis, node_name): attribute_type, multiplier, target, - node_name) + anim_id) return animation_element - def _get_animation_rotation(self, object_, bone_name, axis, node_name): + def _get_animation_rotation(self, object_, bone_name, axis, anim_id): attribute_type = "rotation_euler" multiplier = utils.to_degrees target = "{!s}{!s}{!s}{!s}".format(bone_name, @@ -200,7 +200,7 @@ def _get_animation_rotation(self, object_, bone_name, axis, node_name): attribute_type, multiplier, target, - node_name) + anim_id) return animation_element def _get_animation_attribute(self, @@ -209,9 +209,9 @@ def _get_animation_attribute(self, attribute_type, multiplier, target, - node_name): - id_prefix = "{!s}-{!s}-{!s}_{!s}_{!s}".format(node_name, node_name, - object_.name, attribute_type, axis) + anim_id): + id_prefix = "{!s}-{!s}_{!s}_{!s}".format(anim_id, object_.name, + attribute_type, axis) source_prefix = "#{!s}".format(id_prefix) for curve in object_.animation_data.action.fcurves: diff --git a/io_export_cryblend/rc.py b/io_export_cryblend/rc.py index 9894e07..cd99bfb 100644 --- a/io_export_cryblend/rc.py +++ b/io_export_cryblend/rc.py @@ -68,6 +68,7 @@ def __call__(self): if rc_process is not None: rc_process.wait() self.__recompile(dae_path) + self.__rename_anm_files(dae_path) if self.__config.do_materials: mtl_fix_thread = threading.Thread( @@ -108,6 +109,24 @@ def __recompile(self, dae_path): except: pass + def __rename_anm_files(self, dae_path): + output_path = os.path.dirname(dae_path) + + for group in utils.get_export_nodes(): + if utils.get_node_type(group) == 'anm': + node_name = utils.get_node_name(group) + src_name = "{}_{}".format(node_name, group.name) + src_name = os.path.join(output_path, src_name) + + if os.path.exists(src_name): + dest_name = utils.get_geometry_animation_file_name(group) + dest_name = os.path.join(output_path, dest_name) + + if os.path.exists(dest_name): + os.remove(dest_name) + + os.rename(src_name, dest_name) + def __fix_normalmap_in_mtls(self, rc_process, dae_file): SUCCESS = 0 diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 6d08007..a39c611 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -926,6 +926,53 @@ def apply_animation_scale(armature): cbPrint("Apply Animation was completed.") +def get_animation_id(group): + node_type = get_node_type(group) + node_name = get_node_name(group) + + return "{!s}-{!s}".format(node_name, node_name) + + # Now anm files produces with name as node_name_node_name.anm + # after the process is done anm files are renmaed by rc.py to + # cga_name_node_name.anm + # In the future we may export directly correct name + # with using below codes. But there is a prerequisite for that: + # Dae have to be one main visual_node, others have to be in that main node + # To achieve that we must change a bit visual_exporting process for anm. + # Deficiency at that way process export nodes show as one at console. + if node_type == 'i_caf': + return "{!s}-{!s}".format(node_name, node_name) + else: + cga_node = find_cga_node_from_anm_node(group) + if cga_node: + cga_name = get_node_name(cga_node) + return "{!s}-{!s}".format(node_name, cga_name) + else: + cga_name = group.objects[0].name + return "{!s}-{!s}".format(node_name, cga_name) + + +def get_geometry_animation_file_name(group): + node_type = get_node_type(group) + node_name = get_node_name(group) + + cga_node = find_cga_node_from_anm_node(group) + if cga_node: + cga_name = cga_node.name + return "{!s}_{!s}".format(cga_name, node_name) + else: + cga_name = group.objects[0].name + return "{!s}_{!s}.anm".format(cga_name, node_name) + + +def find_cga_node_from_anm_node(anm_group): + for object_ in anm_group.objects: + for group in object_.users_group: + if get_node_type(group) == 'cga': + return group + return None + + #------------------------------------------------------------------------------ # Bone Geometry: #------------------------------------------------------------------------------ From 87f2bd21ab75479f8e6284d86ddb71c00aeabbef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sun, 19 Jun 2016 18:46:42 +0300 Subject: [PATCH 09/17] Log Animation Informations --- io_export_cryblend/export_animations.py | 10 ++++++++++ io_export_cryblend/utils.py | 5 ++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index d118968..a4782cc 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -82,6 +82,12 @@ def export(self): bpy.context.scene.frame_start = frame_start bpy.context.scene.frame_end = frame_end + print('') + cbPrint(group.name) + cbPrint("Animation is being preparing to process.") + cbPrint("Animation frame range are [{} - {}]".format( + frame_start, frame_end)) + if node_type == 'i_caf': utils.add_fakebones(group) try: @@ -94,6 +100,10 @@ def export(self): if node_type == 'i_caf': utils.remove_fakebones() + cbPrint("Animation has been processed.") + + print('') + self._export_scene(root_element) converter = RCInstance(self._config) diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index a39c611..5684699 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -757,7 +757,6 @@ def process_animation(armature, skeleton): location_list, rotation_list = get_keyframes(armature) set_keyframes(armature, location_list, rotation_list) - cbPrint("Animation was processed.") def get_keyframes(armature): @@ -796,7 +795,7 @@ def get_keyframes(armature): del locations del rotations - cbPrint("Keyframes were appended to lists.") + cbPrint("Keyframes have been appended to lists.") return location_list, rotation_list @@ -812,7 +811,7 @@ def set_keyframes(armature, location_list, rotation_list): set_keyframe(armature, frame, location_list, rotation_list) bpy.context.scene.frame_set(bpy.context.scene.frame_start) - cbPrint("Keyframes were inserted to armature fakebones.") + cbPrint("Keyframes have been inserted to armature fakebones.") def set_keyframe(armature, frame, location_list, rotation_list): From e01124247e5e4053695c5a0cbe1d31aa0c9794e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sun, 19 Jun 2016 18:49:23 +0300 Subject: [PATCH 10/17] Restore frames to initial positions --- io_export_cryblend/export_animations.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index a4782cc..91fdbd5 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -63,6 +63,10 @@ def export(self): lib_visual_scene.appendChild(visual_scene) root_element.appendChild(lib_visual_scene) + initial_frame_active = bpy.context.scene.frame_current + initial_frame_start = bpy.context.scene.frame_start + initial_frame_end = bpy.context.scene.frame_end + ALLOWED_NODE_TYPES = ("i_caf", "anm") for group in utils.get_export_nodes(): @@ -102,6 +106,9 @@ def export(self): cbPrint("Animation has been processed.") + bpy.context.scene.frame_current = initial_frame_active + bpy.context.scene.frame_start = initial_frame_start + bpy.context.scene.frame_end = initial_frame_end print('') self._export_scene(root_element) From 3fa05cb2d7401dcf2db14be58c71d97a257f2f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sun, 19 Jun 2016 18:50:41 +0300 Subject: [PATCH 11/17] Auto detection for markers --- io_export_cryblend/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index bbcca49..8e1e8a0 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -263,6 +263,20 @@ def __init__(self): else: self.node_type = 'anm' + tm = bpy.context.scene.timeline_markers + for marker in tm: + if marker.select: + self.start_m_name = marker.name + self.end_m_name = "{}_E".format(marker.name) + self.is_use_markers = True + + self.node_start = marker.frame + if tm.find(self.end_m_name) != -1: + self.node_end = tm[self.end_m_name].frame + + self.node_name = marker.name + break + return None def execute(self, context): From 417388785b25e65abe41495446072d2fed60bcb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sun, 19 Jun 2016 18:53:33 +0300 Subject: [PATCH 12/17] Changed Visual Scene for Animations --- io_export_cryblend/export_animations.py | 49 +++++++++++++++++++++++++ io_export_cryblend/utils.py | 9 ++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 91fdbd5..730c301 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -340,6 +340,55 @@ def _export_library_visual_scenes(self, visual_scene, group): pass # TODO: Handle No Export Nodes Error + def _write_export_node(self, group, visual_scene): + if not self._config.export_for_lumberyard: + node_name = "CryExportNode_{}".format(utils.get_node_name(group)) + node = self._doc.createElement("node") + node.setAttribute("id", node_name) + node.setIdAttribute("id") + else: + node_name = "{}".format(utils.get_node_name(group)) + node = self._doc.createElement("node") + node.setAttribute("id", node_name) + node.setAttribute("LumberyardExportNode", "1") + node.setIdAttribute("id") + + bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) + self._write_transforms(bpy.context.active_object, node) + bpy.ops.object.delete(use_global=False) + + node = self._write_visual_scene_node(group.objects, node, group) + + extra = self._create_cryengine_extra(group) + node.appendChild(extra) + visual_scene.appendChild(node) + + def _write_visual_scene_node(self, objects, parent_node, group): + node_type = utils.get_node_type(group) + for object_ in objects: + if node_type == 'i_caf' and object_.type == 'ARMATURE': + self._write_bone_list( + [utils.get_root_bone(object_)], object_, parent_node, group) + + elif node_type == 'anm' and object_.type == 'MESH': + prop_name = join(object_.name, + self._create_properties_name(object_, group)) + node = self._doc.createElement("node") + node.setAttribute("id", prop_name) + node.setAttribute("name", prop_name) + node.setIdAttribute("id") + + self._write_transforms(object_, node) + + extra = self._create_cryengine_extra(object_) + if extra is not None: + node.appendChild(extra) + + parent_node.appendChild(node) + + return parent_node + + # ------------------------------------------------------------------- diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 5684699..0aa953a 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -703,7 +703,14 @@ def add_fakebones(group = None): '''Add helpers to track bone transforms.''' scene = bpy.context.scene remove_unused_meshes() - armature = get_armature() + + if group: + for object_ in group.objects: + if object_.type == 'ARMATURE': + armature = object_ + else: + armature = get_armature() + if armature is None: return From 532c789d7ad5985a03d9ff6207366ccf715e5c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Fri, 24 Jun 2016 19:47:06 +0300 Subject: [PATCH 13/17] Nodes from Objects Icon --- io_export_cryblend/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index 8e1e8a0..6ce7d93 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -2404,7 +2404,7 @@ def draw(self, context): layout.operator( "object.selected_to_cry_export_nodes", text="Export Nodes from Objects", - icon="GROUP") + icon="SCENE_DATA") layout.separator() layout.operator( "object.apply_transforms", From 8ab0033030d9a5dbe7d167da9c488125feada68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Fri, 24 Jun 2016 19:49:25 +0300 Subject: [PATCH 14/17] Get Export Node Improvements --- io_export_cryblend/export.py | 16 ++++----- io_export_cryblend/export_animations.py | 4 +-- io_export_cryblend/utils.py | 45 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index 7f017cf..3efc44e 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -88,7 +88,7 @@ def _get_materials(self): materials = OrderedDict() material_counter = {} - for group in utils.get_export_nodes( + for group in utils.get_mesh_export_nodes( self._config.export_selected_nodes): material_counter[group.name] = 50 for object in group.objects: @@ -818,12 +818,12 @@ def _export_library_visual_scenes(self, parent_element): current_element.appendChild(visual_scene) parent_element.appendChild(current_element) - if utils.get_export_nodes(self._config.export_selected_nodes): + if utils.get_mesh_export_nodes(self._config.export_selected_nodes): if utils.are_duplicate_nodes(): message = "Duplicate Node Names" bpy.ops.screen.display_error('INVOKE_DEFAULT', message=message) - for group in utils.get_export_nodes( + for group in utils.get_mesh_export_nodes( self._config.export_selected_nodes): self._write_export_node(group, visual_scene) else: @@ -848,9 +848,9 @@ def _write_export_node(self, group, visual_scene): root_objects = [] for object_ in group.objects: - if (object_.parent is None or object_.type == 'MESH') and \ - not utils.is_bone_geometry(object_): + if utils.is_visual_scene_node_writed(object_, group): root_objects.append(object_) + node = self._write_visual_scene_node(root_objects, node, group) extra = self._create_cryengine_extra(group) @@ -1187,12 +1187,8 @@ def write_scripts(config): dae_path = utils.get_absolute_path_for_rc(filepath) output_path = os.path.dirname(dae_path) - chr_names = [] - for group in utils.get_export_nodes(self._config.export_selected_nodes): - if utils.get_node_type(group) == "chr": - chr_names.append(utils.get_node_name(group)) - for chr_name in chr_names: + for chr_name in utils.get_chr_names(self._config.export_selected_nodes): if config.make_chrparams: filepath = "{}/{}.chrparams".format(output_path, chr_name) contents = utils.generate_file_contents("chrparams") diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 730c301..e33abc1 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -68,7 +68,7 @@ def export(self): initial_frame_end = bpy.context.scene.frame_end ALLOWED_NODE_TYPES = ("i_caf", "anm") - for group in utils.get_export_nodes(): + for group in utils.get_animation_export_nodes(): node_type = utils.get_node_type(group) node_name = utils.get_node_name(group) @@ -330,7 +330,7 @@ def _create_sampler(self, id_prefix, source_prefix): def _export_library_visual_scenes(self, visual_scene, group): - if utils.get_export_nodes(): + if utils.get_animation_export_nodes(): if utils.are_duplicate_nodes(): message = "Duplicate Node Names" bpy.ops.screen.display_error('INVOKE_DEFAULT', message=message) diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 0aa953a..17132f2 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -331,6 +331,42 @@ def get_export_nodes(just_selected=False): return export_nodes +def get_mesh_export_nodes(just_selected=False): + export_nodes = [] + + ALLOWED_NODE_TYPES = ('cgf', 'cga', 'chr', 'skin') + for node in get_export_nodes(just_selected): + if get_node_type(node) in ALLOWED_NODE_TYPES: + export_nodes.append(node) + + return export_nodes + + +def get_chr_names(just_selected=False): + chr_names = [] + + for node in get_export_nodes(just_selected): + if get_node_type(node) == 'chr': + chr_nodes.append(get_node_name(node)) + + return chr_names + + +def get_animation_export_nodes(just_selected=False): + export_nodes = [] + + if just_selected: + return __get_selected_nodes() + + ALLOWED_NODE_TYPES = ('anm', 'i_caf') + for group in bpy.data.groups: + if is_export_node(group) and len(group.objects) > 0: + if get_node_type(group) in ALLOWED_NODE_TYPES: + export_nodes.append(group) + + return export_nodes + + def __get_selected_nodes(): export_nodes = [] @@ -683,6 +719,15 @@ def get_armature_node(object_): return group +def is_visual_scene_node_writed(object_, group): + if is_bone_geometry(object_): + return False + if object_.parent is not None and object_.type != 'MESH': + return False + + return True + + #------------------------------------------------------------------------------ # Fakebones: #------------------------------------------------------------------------------ From 3024bfb6246d6b04224560f9ecb752bb7c1c5c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sat, 25 Jun 2016 15:10:37 +0300 Subject: [PATCH 15/17] ChangeLog 5.2 --- CHANGELOG.md | 19 +++++++++++++++++++ io_export_cryblend/__init__.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cddd9b..29b63c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog: +## 5.2 +#### Compatibility: +* Only compatible with CryEngine 3.5 and up. +* Only compatible with Blender 2.7 and up. +* Supports primary assets: CGF, CGA, CHR, SKIN, ANM, I_CAF. +* Compatible with LumberYard. + +#### UI Changes: +* Added new Animation Node menuitem to create I_CAF and ANM nodes. +* Added new Export Animation menuitem to separate animation and mesh exporting. + +#### New Features: +* Support multiple I_CAF and ANM animation files exporting. +* Animation and character nodes can be located in same project. + +#### Improvements/Fixes: +* CGA and ANM exporting have been fixed. +* Mesh exporting logs have been improved. + ## 5.1 #### Compatibility: * Only compatible with CryEngine 3.5 and up. diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index 6ce7d93..57f13b3 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -35,7 +35,7 @@ "author": "Angelo J. Miner, Duo Oratar, Mikołaj Milej, Daniel White, " "David Marcelis, Özkan Afacan, Oscar Martin Garcia", "blender": (2, 70, 0), - "version": (5, 1, 0), + "version": (5, 2, 0), "location": "CryBlend Menu", "description": "Export assets from Blender to CryEngine 3", "warning": "", From ff0a390b6a5be7ff4e733bedacdc9e616551ac07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sat, 25 Jun 2016 23:54:56 +0300 Subject: [PATCH 16/17] pep8 for 5.2 #6 --- io_export_cryblend/__init__.py | 25 ++++++---- io_export_cryblend/export.py | 16 +++---- io_export_cryblend/export_animations.py | 62 ++++++++++++++----------- io_export_cryblend/rc.py | 2 +- io_export_cryblend/utils.py | 6 +-- 5 files changed, 61 insertions(+), 50 deletions(-) diff --git a/io_export_cryblend/__init__.py b/io_export_cryblend/__init__.py index 57f13b3..68390d7 100644 --- a/io_export_cryblend/__init__.py +++ b/io_export_cryblend/__init__.py @@ -253,11 +253,11 @@ class AddCryAnimationNode(bpy.types.Operator): is_use_markers = BoolProperty(name="Use Markers") start_m_name = StringProperty(name="Marker Start Name") end_m_name = StringProperty(name="Marker End Name") - + def __init__(self): self.node_start = bpy.context.scene.frame_start self.node_end = bpy.context.scene.frame_end - + if bpy.context.active_object.type == 'ARMATURE': self.node_type = 'i_caf' else: @@ -284,14 +284,14 @@ def execute(self, context): if object_: node_start = None node_end = None - + start_name = "{}_Start".format(self.node_name) end_name = "{}_End".format(self.node_name) - + if self.is_use_markers: node_start = self.start_m_name node_end = self.end_m_name - + tm = bpy.context.scene.timeline_markers if tm.find(self.start_m_name) == -1: tm.new(name=self.start_m_name, frame=self.node_start) @@ -303,7 +303,7 @@ def execute(self, context): object_[start_name] = node_start object_[end_name] = node_end - + node_name = "{}.{}".format(self.node_name, self.node_type) group = bpy.data.groups.get(node_name) if group is None: @@ -323,7 +323,9 @@ def execute(self, context): def invoke(self, context, event): object_ = bpy.context.active_object if not object_: - self.report({'ERROR'}, "Please select and active a armature or object.") + self.report( + {'ERROR'}, + "Please select and active a armature or object.") return {'FINISHED'} return context.window_manager.invoke_props_dialog(self) @@ -2110,8 +2112,9 @@ def execute(self, context): if self.run_in_profiler: import cProfile - cProfile.runctx('export_animations.save(config)', {}, - {'export_animations': export_animations, 'config': config}) + cProfile.runctx( + 'export_animations.save(config)', {}, { + 'export_animations': export_animations, 'config': config}) else: export_animations.save(config) @@ -2215,7 +2218,9 @@ def draw(self, context): col.separator() row = col.row(align=True) row.operator("object.add_cry_export_node", text="Add Export Node") - row.operator("object.add_cry_animation_node", text="Add Animation Node") + row.operator( + "object.add_cry_animation_node", + text="Add Animation Node") col.operator( "object.selected_to_cry_export_nodes", text="Export Nodes from Objects") diff --git a/io_export_cryblend/export.py b/io_export_cryblend/export.py index 3efc44e..158f3e0 100644 --- a/io_export_cryblend/export.py +++ b/io_export_cryblend/export.py @@ -677,8 +677,8 @@ def _export_library_controllers(self, parent_element): armature = utils.get_armature_for_object(object_) if armature is not None: self._process_bones(library_node, - object_, - armature) + object_, + armature) parent_element.appendChild(library_node) @@ -861,7 +861,7 @@ def _write_visual_scene_node(self, objects, parent_node, group): for object_ in objects: if object_.type == "MESH" and not utils.is_fakebone(object_): prop_name = join(object_.name, - self._create_properties_name(object_, group)) + self._create_properties_name(object_, group)) node = self._doc.createElement("node") node.setAttribute("id", prop_name) node.setAttribute("name", prop_name) @@ -882,12 +882,12 @@ def _write_visual_scene_node(self, objects, parent_node, group): parent_node.appendChild(node) if object_.parent is not None and object_.parent.type == "ARMATURE": - self._write_bone_list( - [utils.get_root_bone(object_.parent)], object_, parent_node, group) + self._write_bone_list([utils.get_root_bone( + object_.parent)], object_, parent_node, group) elif object_.type == "ARMATURE" and utils.is_physical(object_): - self._write_bone_list( - [utils.get_root_bone(object_)], object_, parent_node, group) + self._write_bone_list([utils.get_root_bone( + object_)], object_, parent_node, group) return parent_node @@ -1109,7 +1109,7 @@ def _create_user_defined_property(self, prop, node): udp = self._doc.createTextNode("{!s}".format(prop[1])) else: udp = self._doc.createTextNode("{!s}=".format(prop[0]) - + "{!s}".format(prop[1])) + + "{!s}".format(prop[1])) node.appendChild(udp) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index e33abc1..8e2c79e 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -50,12 +50,12 @@ def export(self): root_element.setAttribute("version", "1.4.1") self._doc.appendChild(root_element) self._create_file_header(root_element) - + libanmcl = self._doc.createElement("library_animation_clips") libanm = self._doc.createElement("library_animations") root_element.appendChild(libanmcl) root_element.appendChild(libanm) - + lib_visual_scene = self._doc.createElement("library_visual_scenes") visual_scene = self._doc.createElement("visual_scene") visual_scene.setAttribute("id", "scene") @@ -124,7 +124,8 @@ def _prepare_for_export(self): # Library Animations and Clips: --> Animations, F-Curves # ----------------------------------------------------------------------------- - def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group): + def _export_library_animation_clips_and_animations( + self, libanmcl, libanm, group): scene = bpy.context.scene anim_id = utils.get_animation_id(group) @@ -134,7 +135,7 @@ def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group animation_clip.setAttribute("start", "{:f}".format( utils.frame_to_time(scene.frame_start))) animation_clip.setAttribute("end", "{:f}".format( - utils.frame_to_time(scene.frame_end))) + utils.frame_to_time(scene.frame_end))) is_animation = False for object_ in group.objects: @@ -164,7 +165,8 @@ def _export_library_animation_clips_and_animations(self, libanmcl, libanm, group if is_animation: libanmcl.appendChild(animation_clip) - def _export_instance_animation_parameters(self, object_, animation_clip, anim_id): + def _export_instance_animation_parameters( + self, object_, animation_clip, anim_id): location_exists = rotation_exists = False for curve in object_.animation_data.action.fcurves: for axis in iter(AXES): @@ -183,7 +185,12 @@ def _export_instance_animation_parameters(self, object_, animation_clip, anim_id self._export_instance_parameter( object_, animation_clip, "rotation_euler", anim_id) - def _export_instance_parameter(self, object_, animation_clip, parameter, anim_id): + def _export_instance_parameter( + self, + object_, + animation_clip, + parameter, + anim_id): for axis in iter(AXES): inst = self._doc.createElement("instance_animation") inst.setAttribute( @@ -197,11 +204,11 @@ def _get_animation_location(self, object_, bone_name, axis, anim_id): target = "{!s}{!s}{!s}".format(bone_name, "/translation.", axis) animation_element = self._get_animation_attribute(object_, - axis, - attribute_type, - multiplier, - target, - anim_id) + axis, + attribute_type, + multiplier, + target, + anim_id) return animation_element def _get_animation_rotation(self, object_, bone_name, axis, anim_id): @@ -213,22 +220,22 @@ def _get_animation_rotation(self, object_, bone_name, axis, anim_id): ".ANGLE") animation_element = self._get_animation_attribute(object_, - axis, - attribute_type, - multiplier, - target, - anim_id) + axis, + attribute_type, + multiplier, + target, + anim_id) return animation_element def _get_animation_attribute(self, - object_, - axis, - attribute_type, - multiplier, - target, - anim_id): + object_, + axis, + attribute_type, + multiplier, + target, + anim_id): id_prefix = "{!s}-{!s}_{!s}_{!s}".format(anim_id, object_.name, - attribute_type, axis) + attribute_type, axis) source_prefix = "#{!s}".format(id_prefix) for curve in object_.animation_data.action.fcurves: @@ -339,7 +346,6 @@ def _export_library_visual_scenes(self, visual_scene, group): else: pass # TODO: Handle No Export Nodes Error - def _write_export_node(self, group, visual_scene): if not self._config.export_for_lumberyard: node_name = "CryExportNode_{}".format(utils.get_node_name(group)) @@ -367,12 +373,12 @@ def _write_visual_scene_node(self, objects, parent_node, group): node_type = utils.get_node_type(group) for object_ in objects: if node_type == 'i_caf' and object_.type == 'ARMATURE': - self._write_bone_list( - [utils.get_root_bone(object_)], object_, parent_node, group) - + self._write_bone_list([utils.get_root_bone( + object_)], object_, parent_node, group) + elif node_type == 'anm' and object_.type == 'MESH': prop_name = join(object_.name, - self._create_properties_name(object_, group)) + self._create_properties_name(object_, group)) node = self._doc.createElement("node") node.setAttribute("id", prop_name) node.setAttribute("name", prop_name) diff --git a/io_export_cryblend/rc.py b/io_export_cryblend/rc.py index cd99bfb..ed3a01d 100644 --- a/io_export_cryblend/rc.py +++ b/io_export_cryblend/rc.py @@ -124,7 +124,7 @@ def __rename_anm_files(self, dae_path): if os.path.exists(dest_name): os.remove(dest_name) - + os.rename(src_name, dest_name) def __fix_normalmap_in_mtls(self, rc_process, dae_file): diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 17132f2..74f6117 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -744,7 +744,7 @@ def is_fakebone(object_): return False -def add_fakebones(group = None): +def add_fakebones(group=None): '''Add helpers to track bone transforms.''' scene = bpy.context.scene remove_unused_meshes() @@ -1091,8 +1091,8 @@ def get_animation_node_range(object_, node_name): try: start_frame = object_["{}_Start".format(node_name)] end_frame = object_["{}_End".format(node_name)] - - if type(start_frame) is str and type(end_frame) is str: + + if isinstance(start_frame, str) and isinstance(end_frame, str): tm = bpy.context.scene.timeline_markers if tm.find(start_frame) != -1 and tm.find(end_frame) != -1: return tm[start_frame].frame, tm[end_frame].frame From f6d601ac7e37a75d7f9fdcd0ac1484f17f2f9c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96zkan=20Afacan?= Date: Sun, 26 Jun 2016 16:04:29 +0300 Subject: [PATCH 17/17] Mesh Animation Fix according to PEP8 --- io_export_cryblend/export_animations.py | 5 +++-- io_export_cryblend/utils.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/io_export_cryblend/export_animations.py b/io_export_cryblend/export_animations.py index 8e2c79e..8f289b7 100644 --- a/io_export_cryblend/export_animations.py +++ b/io_export_cryblend/export_animations.py @@ -377,8 +377,9 @@ def _write_visual_scene_node(self, objects, parent_node, group): object_)], object_, parent_node, group) elif node_type == 'anm' and object_.type == 'MESH': - prop_name = join(object_.name, - self._create_properties_name(object_, group)) + prop_name = "{}{}".format( + object_.name, self._create_properties_name( + object_, group)) node = self._doc.createElement("node") node.setAttribute("id", prop_name) node.setAttribute("name", prop_name) diff --git a/io_export_cryblend/utils.py b/io_export_cryblend/utils.py index 74f6117..5950ec4 100644 --- a/io_export_cryblend/utils.py +++ b/io_export_cryblend/utils.py @@ -1009,8 +1009,8 @@ def get_geometry_animation_file_name(group): cga_node = find_cga_node_from_anm_node(group) if cga_node: - cga_name = cga_node.name - return "{!s}_{!s}".format(cga_name, node_name) + cga_name = get_node_name(cga_node) + return "{!s}_{!s}.anm".format(cga_name, node_name) else: cga_name = group.objects[0].name return "{!s}_{!s}.anm".format(cga_name, node_name)