glTF importer: Import extra data as custom properties

This commit is contained in:
Julien Duroure 2019-10-12 17:15:22 +02:00
parent b9b1814a4c
commit ecdaef9523
13 changed files with 123 additions and 11 deletions

View File

@ -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, 6),
"version": (1, 0, 7),
'blender': (2, 81, 6),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',

View File

@ -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

View File

@ -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
@ -124,6 +124,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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
@ -219,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

View File

@ -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":

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)