diff options
Diffstat (limited to 'io_scene_gltf2')
19 files changed, 273 insertions, 36 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 36fda5ce..06012f5e 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (1, 0, 4), + "version": (1, 0, 9), 'blender': (2, 81, 6), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', @@ -57,7 +57,8 @@ import bpy from bpy.props import (StringProperty, BoolProperty, EnumProperty, - IntProperty) + IntProperty, + CollectionProperty) from bpy.types import Operator from bpy_extras.io_utils import ImportHelper, ExportHelper @@ -256,6 +257,12 @@ class ExportGLTF2_Base: default=True ) + export_def_bones: BoolProperty( + name='Export Deformation bones only', + description='Export Deformation bones only (and needed bones for hierarchy)', + default=False + ) + export_current_frame: BoolProperty( name='Use Current Frame', description='Export the scene in the current animation frame', @@ -389,11 +396,16 @@ class ExportGLTF2_Base: if self.export_animations: export_settings['gltf_frame_range'] = self.export_frame_range export_settings['gltf_force_sampling'] = self.export_force_sampling + if self.export_force_sampling: + export_settings['gltf_def_bones'] = self.export_def_bones + else: + export_settings['gltf_def_bones'] = False export_settings['gltf_nla_strips'] = self.export_nla_strips else: export_settings['gltf_frame_range'] = False export_settings['gltf_move_keyframes'] = False export_settings['gltf_force_sampling'] = False + export_settings['gltf_def_bones'] = False export_settings['gltf_skins'] = self.export_skins if self.export_skins: export_settings['gltf_all_vertex_influences'] = self.export_all_influences @@ -642,6 +654,10 @@ class GLTF_PT_export_animation_export(bpy.types.Panel): layout.prop(operator, 'export_force_sampling') layout.prop(operator, 'export_nla_strips') + row = layout.row() + row.active = operator.export_force_sampling + row.prop(operator, 'export_def_bones') + class GLTF_PT_export_animation_shapekeys(bpy.types.Panel): bl_space_type = 'FILE_BROWSER' @@ -730,6 +746,11 @@ class ImportGLTF2(Operator, ImportHelper): filter_glob: StringProperty(default="*.glb;*.gltf", options={'HIDDEN'}) + files: CollectionProperty( + name="File Path", + type=bpy.types.OperatorFileListElement, + ) + loglevel: IntProperty( name='Log Level', description="Log Level") @@ -758,14 +779,30 @@ class ImportGLTF2(Operator, ImportHelper): return self.import_gltf2(context) def import_gltf2(self, context): - import time - from .io.imp.gltf2_io_gltf import glTFImporter - from .blender.imp.gltf2_blender_gltf import BlenderGlTF + import os self.set_debug_log() import_settings = self.as_keywords() - self.gltf_importer = glTFImporter(self.filepath, import_settings) + if self.files: + # Multiple file import + ret = {'CANCELLED'} + dirname = os.path.dirname(self.filepath) + for file in self.files: + path = os.path.join(dirname, file.name) + if self.unit_import(path, import_settings) == {'FINISHED'}: + ret = {'FINISHED'} + return ret + else: + # Single file import + return self.unit_import(self.filepath, import_settings) + + def unit_import(self, filename, import_settings): + import time + from .io.imp.gltf2_io_gltf import glTFImporter + from .blender.imp.gltf2_blender_gltf import BlenderGlTF + + self.gltf_importer = glTFImporter(filename, import_settings) success, txt = self.gltf_importer.read() if not success: self.report({'ERROR'}, txt) diff --git a/io_scene_gltf2/blender/com/gltf2_blender_extras.py b/io_scene_gltf2/blender/com/gltf2_blender_extras.py new file mode 100644 index 00000000..0be942a0 --- /dev/null +++ b/io_scene_gltf2/blender/com/gltf2_blender_extras.py @@ -0,0 +1,91 @@ +# Copyright 2018-2019 The glTF-Blender-IO authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import bpy +from .gltf2_blender_json import is_json_convertible + + +# Custom properties, which are in most cases present and should not be imported/exported. +BLACK_LIST = ['cycles', 'cycles_visibility', 'cycles_curves', '_RNA_UI'] + + +def generate_extras(blender_element): + """Filter and create a custom property, which is stored in the glTF extra field.""" + if not blender_element: + return None + + extras = {} + + for custom_property in blender_element.keys(): + if custom_property in BLACK_LIST: + continue + + value = __to_json_compatible(blender_element[custom_property]) + + if value is not None: + extras[custom_property] = value + + if not extras: + return None + + return extras + + +def __to_json_compatible(value): + """Make a value (usually a custom property) compatible with json""" + + if isinstance(value, bpy.types.ID): + return value + + elif isinstance(value, str): + return value + + elif isinstance(value, (int, float)): + return value + + # for list classes + elif isinstance(value, list): + value = list(value) + # make sure contents are json-compatible too + for index in range(len(value)): + value[index] = __to_json_compatible(value[index]) + return value + + # for IDPropertyArray classes + elif hasattr(value, "to_list"): + value = value.to_list() + return value + + elif hasattr(value, "to_dict"): + value = value.to_dict() + if is_json_convertible(value): + return value + + return None + + +def set_extras(blender_element, extras, exclude=[]): + """Copy extras onto a Blender object.""" + if not extras or not isinstance(extras, dict): + return + + for custom_property, value in extras.items(): + if custom_property in BLACK_LIST: + continue + if custom_property in exclude: + continue + + blender_element[custom_property] = value + diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather.py index 2e4bfe31..f4fd70dd 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather.py @@ -19,7 +19,7 @@ from io_scene_gltf2.io.com.gltf2_io_debug import print_console from io_scene_gltf2.blender.exp import gltf2_blender_gather_nodes from io_scene_gltf2.blender.exp import gltf2_blender_gather_animations from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached -from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.blender.exp import gltf2_blender_export_keys @@ -97,6 +97,14 @@ def __gather_animations(blender_scene, export_settings): to_delete_idx.append(anim_idx) + # Merging extras + # Warning, some values can be overwritten if present in multiple merged animations + if animations[anim_idx].extras is not None: + for k in animations[anim_idx].extras.keys(): + if animations[base_animation_idx].extras is None: + animations[base_animation_idx].extras = {} + animations[base_animation_idx].extras[k] = animations[anim_idx].extras[k] + offset_sampler = len(animations[base_animation_idx].samplers) for sampler in animations[anim_idx].samplers: animations[base_animation_idx].samplers.append(sampler) @@ -124,6 +132,6 @@ def __gather_animations(blender_scene, export_settings): def __gather_extras(blender_object, export_settings): if export_settings[gltf2_blender_export_keys.EXTRAS]: - return gltf2_blender_generate_extras.generate_extras(blender_object) + return generate_extras(blender_object) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py index 04028d20..fa0f9976 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channel_target.py @@ -19,7 +19,7 @@ from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.blender.exp import gltf2_blender_gather_nodes from io_scene_gltf2.blender.exp import gltf2_blender_gather_joints - +from io_scene_gltf2.blender.exp import gltf2_blender_gather_skins @cached def gather_animation_channel_target(channels: typing.Tuple[bpy.types.FCurve], @@ -66,7 +66,12 @@ def __gather_node(channels: typing.Tuple[bpy.types.FCurve], blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0]) if isinstance(blender_bone, bpy.types.PoseBone): - return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings) + if export_settings["gltf_def_bones"] is False: + return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings) + else: + bones, _, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_object) + if blender_bone.name in [b.name for b in bones]: + return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings) return gltf2_blender_gather_nodes.gather_node(blender_object, None, export_settings) diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py index edee0971..611cd74a 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animation_channels.py @@ -22,6 +22,7 @@ from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.blender.exp import gltf2_blender_gather_animation_samplers from io_scene_gltf2.blender.exp import gltf2_blender_gather_animation_channel_target from io_scene_gltf2.blender.exp import gltf2_blender_get +from io_scene_gltf2.blender.exp import gltf2_blender_gather_skins @cached @@ -58,7 +59,14 @@ def gather_animation_channels(blender_action: bpy.types.Action, return [] # Then bake all bones - for bone in blender_object.data.bones: + bones_to_be_animated = [] + if export_settings["gltf_def_bones"] is False: + bones_to_be_animated = blender_object.data.bones + else: + bones_to_be_animated, _, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_object) + bones_to_be_animated = [blender_object.pose.bones[b.name] for b in bones_to_be_animated] + + for bone in bones_to_be_animated: for p in ["location", "rotation_quaternion", "scale"]: channel = __gather_animation_channel( (), diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py index de205913..d55c20b1 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_animations.py @@ -18,6 +18,7 @@ import typing from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.blender.exp import gltf2_blender_gather_animation_channels from io_scene_gltf2.io.com.gltf2_io_debug import print_console +from ..com.gltf2_blender_extras import generate_extras def gather_animations(blender_object: bpy.types.Object, @@ -139,6 +140,9 @@ def __gather_extras(blender_action: bpy.types.Action, blender_object: bpy.types.Object, export_settings ) -> typing.Any: + + if export_settings['gltf_extras']: + return generate_extras(blender_action) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py index e6d82121..3cde0fcb 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_cameras.py @@ -14,7 +14,7 @@ from . import gltf2_blender_export_keys from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached -from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.io.com import gltf2_io import bpy @@ -46,7 +46,7 @@ def __gather_extensions(blender_camera, export_settings): def __gather_extras(blender_camera, export_settings): if export_settings['gltf_extras']: - return gltf2_blender_generate_extras.generate_extras(blender_camera) + return generate_extras(blender_camera) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_joints.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_joints.py index 2059ea88..dce70c31 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_joints.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_joints.py @@ -20,6 +20,7 @@ from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.com import gltf2_io_debug from io_scene_gltf2.blender.exp import gltf2_blender_extract from io_scene_gltf2.blender.com import gltf2_blender_math +from io_scene_gltf2.blender.exp import gltf2_blender_gather_skins @cached @@ -55,8 +56,15 @@ def gather_joint(blender_bone, export_settings): # traverse into children children = [] - for bone in blender_bone.children: - children.append(gather_joint(bone, export_settings)) + + if export_settings["gltf_def_bones"] is False: + for bone in blender_bone.children: + children.append(gather_joint(bone, export_settings)) + else: + _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_bone.id_data) + if blender_bone.name in children_.keys(): + for bone in children_[blender_bone.name]: + children.append(gather_joint(blender_bone.id_data.pose.bones[bone], export_settings)) # finally add to the joints array containing all the joints in the hierarchy return gltf2_io.Node( diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_lights.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_lights.py index c87318d0..dbb59e21 100644 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_lights.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_lights.py @@ -17,6 +17,7 @@ import math from typing import Optional, List, Dict, Any from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.io.com import gltf2_io_lights_punctual from io_scene_gltf2.io.com import gltf2_io_debug @@ -112,6 +113,8 @@ def __gather_extensions(blender_lamp, export_settings) -> Optional[dict]: def __gather_extras(blender_lamp, export_settings) -> Optional[Any]: + if export_settings['gltf_extras']: + return generate_extras(blender_lamp) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py index 3f4466f5..9b9a9abe 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py @@ -23,7 +23,7 @@ from io_scene_gltf2.blender.exp import gltf2_blender_gather_material_occlusion_t from io_scene_gltf2.blender.exp import gltf2_blender_search_node_tree from io_scene_gltf2.blender.exp import gltf2_blender_gather_materials_pbr_metallic_roughness -from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.blender.exp import gltf2_blender_get @@ -136,7 +136,7 @@ def __gather_extensions(blender_material, export_settings): def __gather_extras(blender_material, export_settings): if export_settings['gltf_extras']: - return gltf2_blender_generate_extras.generate_extras(blender_material) + return generate_extras(blender_material) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py index ca79ef33..3af26ced 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_mesh.py @@ -18,7 +18,7 @@ from .gltf2_blender_export_keys import MORPH from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.blender.exp import gltf2_blender_gather_primitives -from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.io.com.gltf2_io_debug import print_console @@ -76,7 +76,7 @@ def __gather_extras(blender_mesh: bpy.types.Mesh, extras = {} if export_settings['gltf_extras']: - extras = gltf2_blender_generate_extras.generate_extras(blender_mesh) or {} + extras = generate_extras(blender_mesh) or {} if export_settings[MORPH] and blender_mesh.shape_keys: morph_max = len(blender_mesh.shape_keys.key_blocks) - 1 diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py index 32745027..6ab77945 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_nodes.py @@ -25,7 +25,7 @@ from io_scene_gltf2.blender.exp import gltf2_blender_gather_mesh from io_scene_gltf2.blender.exp import gltf2_blender_gather_joints from io_scene_gltf2.blender.exp import gltf2_blender_extract from io_scene_gltf2.blender.exp import gltf2_blender_gather_lights -from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras +from ..com.gltf2_blender_extras import generate_extras from io_scene_gltf2.io.com import gltf2_io from io_scene_gltf2.io.com import gltf2_io_extensions @@ -135,7 +135,12 @@ def __gather_children(blender_object, blender_scene, export_settings): # blender bones if blender_object.type == "ARMATURE": root_joints = [] - for blender_bone in blender_object.pose.bones: + if export_settings["gltf_def_bones"] is False: + bones = blender_object.pose.bones + else: + bones, _, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_object) + bones = [blender_object.pose.bones[b.name] for b in bones] + for blender_bone in bones: if not blender_bone.parent: joint = gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings) children.append(joint) @@ -214,7 +219,7 @@ def __gather_extensions(blender_object, export_settings): def __gather_extras(blender_object, export_settings): if export_settings['gltf_extras']: - return gltf2_blender_generate_extras.generate_extras(blender_object) + return generate_extras(blender_object) return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py index 59af7d72..18503fdd 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_skins.py @@ -67,11 +67,14 @@ def __gather_inverse_bind_matrices(blender_object, export_settings): axis_basis_change = mathutils.Matrix( ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0))) - # build the hierarchy of nodes out of the bones - root_bones = [] - for blender_bone in blender_object.pose.bones: - if not blender_bone.parent: - root_bones.append(blender_bone) + if export_settings['gltf_def_bones'] is False: + # build the hierarchy of nodes out of the bones + root_bones = [] + for blender_bone in blender_object.pose.bones: + if not blender_bone.parent: + root_bones.append(blender_bone) + else: + _, children_, root_bones = get_bone_tree(None, blender_object) matrices = [] @@ -86,8 +89,13 @@ def __gather_inverse_bind_matrices(blender_object, export_settings): ).inverted() matrices.append(inverse_bind_matrix) - for child in bone.children: - __collect_matrices(child) + if export_settings['gltf_def_bones'] is False: + for child in bone.children: + __collect_matrices(child) + else: + if bone.name in children_.keys(): + for child in children_[bone.name]: + __collect_matrices(blender_object.pose.bones[child]) # start with the "root" bones and recurse into children, in the same ordering as the how joints are gathered for root_bone in root_bones: @@ -114,18 +122,28 @@ def __gather_inverse_bind_matrices(blender_object, export_settings): def __gather_joints(blender_object, export_settings): root_joints = [] - # build the hierarchy of nodes out of the bones - for blender_bone in blender_object.pose.bones: - if not blender_bone.parent: - root_joints.append(gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)) + if export_settings['gltf_def_bones'] is False: + # build the hierarchy of nodes out of the bones + for blender_bone in blender_object.pose.bones: + if not blender_bone.parent: + root_joints.append(gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)) + else: + _, children_, root_joints = get_bone_tree(None, blender_object) + root_joints = [gltf2_blender_gather_joints.gather_joint(i, export_settings) for i in root_joints] # joints is a flat list containing all nodes belonging to the skin joints = [] def __collect_joints(node): joints.append(node) - for child in node.children: - __collect_joints(child) + if export_settings['gltf_def_bones'] is False: + for child in node.children: + __collect_joints(child) + else: + if node.name in children_.keys(): + for child in children_[node.name]: + __collect_joints(gltf2_blender_gather_joints.gather_joint(blender_object.pose.bones[child], export_settings)) + for joint in root_joints: __collect_joints(joint) @@ -140,3 +158,30 @@ def __gather_skeleton(blender_object, export_settings): # In the future support the result of https://github.com/KhronosGroup/glTF/pull/1195 return None # gltf2_blender_gather_nodes.gather_node(blender_object, blender_scene, export_settings) +@cached +def get_bone_tree(blender_dummy, blender_object): + + bones = [] + children = {} + root_bones = [] + + def get_parent(bone): + bones.append(bone.name) + if bone.parent is not None: + if bone.parent.name not in children.keys(): + children[bone.parent.name] = [] + children[bone.parent.name].append(bone.name) + get_parent(bone.parent) + else: + root_bones.append(bone.name) + + for bone in [b for b in blender_object.data.bones if b.use_deform is True]: + get_parent(bone) + + # remove duplicates + for k, v in children.items(): + children[k] = list(set(v)) + list_ = list(set(bones)) + root_ = list(set(root_bones)) + return [blender_object.data.bones[b] for b in list_], children, [blender_object.pose.bones[b] for b in root_] + diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_camera.py b/io_scene_gltf2/blender/imp/gltf2_blender_camera.py index d746c1b1..ec5f0ee4 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_camera.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_camera.py @@ -13,6 +13,7 @@ # limitations under the License. import bpy +from ..com.gltf2_blender_extras import set_extras class BlenderCamera(): @@ -29,6 +30,7 @@ class BlenderCamera(): pycamera.name = "Camera" cam = bpy.data.cameras.new(pycamera.name) + set_extras(cam, pycamera.extras) # Blender create a perspective camera by default if pycamera.type == "orthographic": diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_light.py b/io_scene_gltf2/blender/imp/gltf2_blender_light.py index 492c552e..6213091e 100644 --- a/io_scene_gltf2/blender/imp/gltf2_blender_light.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_light.py @@ -15,6 +15,8 @@ import bpy from math import pi +from ..com.gltf2_blender_extras import set_extras + class BlenderLight(): """Blender Light.""" @@ -45,6 +47,8 @@ class BlenderLight(): else: bpy.data.scenes[gltf.blender_scene].collection.objects.link(obj) + set_extras(obj.data, pylight.get('extras')) + return obj @staticmethod diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_material.py b/io_scene_gltf2/blender/imp/gltf2_blender_material.py index 55be1626..c5e3b51c 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_material.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_material.py @@ -13,6 +13,8 @@ # limitations under the License. import bpy + +from ..com.gltf2_blender_extras import set_extras from .gltf2_blender_pbrMetallicRoughness import BlenderPbr from .gltf2_blender_KHR_materials_pbrSpecularGlossiness import BlenderKHR_materials_pbrSpecularGlossiness from .gltf2_blender_KHR_materials_unlit import BlenderKHR_materials_unlit @@ -49,6 +51,8 @@ class BlenderMaterial(): mat = bpy.data.materials.new(name) pymaterial.blender_material[vertex_color] = mat.name + set_extras(mat, pymaterial.extras) + mat.use_backface_culling = (pymaterial.double_sided != True) ignore_map = False diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py index 1f7f7b66..eb92d9a3 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_mesh.py @@ -16,6 +16,7 @@ import bpy import bmesh from mathutils import Vector +from ..com.gltf2_blender_extras import set_extras from .gltf2_blender_material import BlenderMaterial from .gltf2_blender_primitive import BlenderPrimitive from ...io.imp.gltf2_io_binary import BinaryData @@ -75,6 +76,8 @@ class BlenderMesh(): mesh.materials.append(bpy.data.materials[name_material]) mesh.update() + set_extras(mesh, pymesh.extras, exclude=['targetNames']) + pymesh.blender_name = mesh.name # Clear accessor cache after all primitives are done diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_node.py b/io_scene_gltf2/blender/imp/gltf2_blender_node.py index 6a40aecc..a02514de 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_node.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_node.py @@ -13,6 +13,7 @@ # limitations under the License. import bpy +from ..com.gltf2_blender_extras import set_extras from .gltf2_blender_mesh import BlenderMesh from .gltf2_blender_camera import BlenderCamera from .gltf2_blender_skin import BlenderSkin @@ -76,6 +77,7 @@ class BlenderNode(): name = "Object_" + str(node_idx) obj = bpy.data.objects.new(name, mesh) + set_extras(obj, pynode.extras) obj.rotation_mode = 'QUATERNION' if gltf.blender_active_collection is not None: bpy.data.collections[gltf.blender_active_collection].objects.link(obj) @@ -104,6 +106,7 @@ class BlenderNode(): else: gltf.log.info("Blender create Camera node") obj = BlenderCamera.create(gltf, pynode.camera) + set_extras(obj, pynode.extras) BlenderNode.set_transforms(gltf, node_idx, pynode, obj, parent) # TODO default rotation of cameras ? pynode.blender_object = obj.name BlenderNode.set_parent(gltf, obj, parent) @@ -134,6 +137,7 @@ class BlenderNode(): if pynode.extensions is not None: if 'KHR_lights_punctual' in pynode.extensions.keys(): obj = BlenderLight.create(gltf, pynode.extensions['KHR_lights_punctual']['light']) + set_extras(obj, pynode.extras) obj.rotation_mode = 'QUATERNION' BlenderNode.set_transforms(gltf, node_idx, pynode, obj, parent, correction=True) pynode.blender_object = obj.name @@ -154,6 +158,7 @@ class BlenderNode(): else: gltf.log.info("Blender create Empty node") obj = bpy.data.objects.new("Node", None) + set_extras(obj, pynode.extras) obj.rotation_mode = 'QUATERNION' if gltf.blender_active_collection is not None: bpy.data.collections[gltf.blender_active_collection].objects.link(obj) diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_skin.py b/io_scene_gltf2/blender/imp/gltf2_blender_skin.py index 2758b348..00996371 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_skin.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_skin.py @@ -17,7 +17,7 @@ import bpy from mathutils import Vector, Matrix from ..com.gltf2_blender_conversion import matrix_gltf_to_blender, scale_to_matrix from ...io.imp.gltf2_io_binary import BinaryData - +from ..com.gltf2_blender_extras import set_extras class BlenderSkin(): """Blender Skinning / Armature.""" @@ -130,10 +130,15 @@ class BlenderSkin(): pynode.blender_bone_name = bone.name pynode.blender_armature_name = pyskin.blender_armature_name bone.tail = Vector((0.0, 1.0, 0.0)) # Needed to keep bone alive + # Custom prop on edit bone + set_extras(bone, pynode.extras) # set bind and pose transforms BlenderSkin.set_bone_transforms(gltf, skin_id, bone, node_id, parent) bpy.ops.object.mode_set(mode="OBJECT") + # Custom prop on pose bone + if bone.name in obj.pose.bones: + set_extras(obj.pose.bones[bone.name], pynode.extras) @staticmethod def create_vertex_groups(gltf, skin_id): |