From 74c7171880b70c9266c60371034e4b33a17adf37 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Sun, 28 Nov 2021 03:10:15 -0500 Subject: [PATCH 01/43] test support for importing some hubs components --- __init__.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/__init__.py b/__init__.py index b98c7f8c..e8fc8db9 100644 --- a/__init__.py +++ b/__init__.py @@ -29,14 +29,54 @@ def get_version_string(): # ideally we can resolve this upstream somehow https://github.com/KhronosGroup/glTF-Blender-IO/issues/1009 from io_scene_gltf2.blender.exp import gltf2_blender_export from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions +from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode orig_gather_gltf = gltf2_blender_export.__gather_gltf +orig_BlenderNode_create_object = BlenderNode.create_object + def patched_gather_gltf(exporter, export_settings): orig_gather_gltf(exporter, export_settings) export_user_extensions('hubs_gather_gltf_hook', export_settings, exporter._GlTF2Exporter__gltf) exporter._GlTF2Exporter__traverse(exporter._GlTF2Exporter__gltf.extensions) +@staticmethod +def patched_BlenderNode_create_object(gltf, vnode_id): + obj = orig_BlenderNode_create_object(gltf, vnode_id) + + vnode = gltf.vnodes[vnode_id] + node = None + + if vnode.camera_node_idx is not None: + parent_vnode = gltf.vnodes[vnode.parent] + if parent_vnode.name: + node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] + + else: + if vnode.name: + node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + + + if node is not None: + extensions = node.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + print(node.name) + print(obj) + bpy.context.view_layer.objects.active = obj + + bpy.ops.wm.add_hubs_component(object_source="object", component_name=glb_component_name) + + blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") + + for property_name, property_value in glb_component_value.items(): + blender_component[property_name] = property_value + + return obj + def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf + BlenderNode.create_object = patched_BlenderNode_create_object components.register() @@ -47,6 +87,7 @@ def register(): def unregister(): gltf2_blender_export.__gather_gltf = orig_gather_gltf + BlenderNode.create_object = orig_BlenderNode_create_object components.unregister() settings.unregister() From 109fef03b94aed386549dd9aff3d0eae58a4e24b Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Mon, 29 Nov 2021 04:31:44 -0500 Subject: [PATCH 02/43] More support for Hubs components. Everything works on object components except for enum menus and kit-alt-materials. No material or scene Hubs components imported yet. --- __init__.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index e8fc8db9..929b20bd 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,7 @@ import bpy import uuid +import traceback +import re from . import settings from . import components @@ -40,6 +42,7 @@ def patched_gather_gltf(exporter, export_settings): @staticmethod def patched_BlenderNode_create_object(gltf, vnode_id): + #print("loading hubs components") obj = orig_BlenderNode_create_object(gltf, vnode_id) vnode = gltf.vnodes[vnode_id] @@ -55,22 +58,73 @@ def patched_BlenderNode_create_object(gltf, vnode_id): node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + #print(f"node is: {node}") if node is not None: extensions = node.extensions + #print(f"extensions are: {extensions}") if extensions: MOZ_hubs_components = extensions.get('MOZ_hubs_components') + #print(f"MOZ_hubs_components are: {MOZ_hubs_components}") if MOZ_hubs_components: for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - print(node.name) - print(obj) + if glb_component_name == 'networked': + return + + print(f"Node Name: {node.name}") + print(f"Object: {obj}") + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") bpy.context.view_layer.objects.active = obj - bpy.ops.wm.add_hubs_component(object_source="object", component_name=glb_component_name) + try: + bpy.ops.wm.add_hubs_component(object_source="object", component_name=glb_component_name) + + blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") + + if glb_component_name == 'audio-target': + for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': + blender_component[property_name] = bpy.data.objects[gltf.vnodes[property_value['index']].name] + + else: + if blender_component.bl_rna.properties[property_name].type == 'FLOAT': + property_value = float(property_value) + print(f"{property_name} = {property_value}") + blender_component[property_name] = property_value + + else: + for property_name, property_value in glb_component_value.items(): + + if isinstance(property_value, dict): + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + if blender_component.bl_rna.properties[property_name].type == 'FLOAT': + subproperty_value = float(subproperty_value) + + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value + + else: + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + if blender_component.bl_rna.properties[property_name].type == 'FLOAT': + property_value = float(property_value) - blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") + print(f"{property_name} = {property_value}") + blender_component[property_name] = property_value - for property_name, property_value in glb_component_value.items(): - blender_component[property_name] = property_value + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") return obj From cbeda4be43eb807ad955155049f2a00666483c57 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 2 Dec 2021 06:05:47 -0500 Subject: [PATCH 03/43] Fix enum menus, simplify property assignment and make it consistent. Kit-alt-materials are in the process of being reworked. --- __init__.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/__init__.py b/__init__.py index 929b20bd..54ec5d44 100644 --- a/__init__.py +++ b/__init__.py @@ -83,14 +83,16 @@ def patched_BlenderNode_create_object(gltf, vnode_id): if glb_component_name == 'audio-target': for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': - blender_component[property_name] = bpy.data.objects[gltf.vnodes[property_value['index']].name] + setattr(blender_component, property_name, bpy.data.objects[gltf.vnodes[property_value['index']].name]) else: - if blender_component.bl_rna.properties[property_name].type == 'FLOAT': - property_value = float(property_value) print(f"{property_name} = {property_value}") - blender_component[property_name] = property_value + setattr(blender_component, property_name, property_value) + + elif glb_component_name == 'kit-alt-materials': + pass else: for property_name, property_value in glb_component_value.items(): @@ -98,9 +100,6 @@ def patched_BlenderNode_create_object(gltf, vnode_id): if isinstance(property_value, dict): blender_subcomponent = getattr(blender_component, property_name) for x, subproperty_value in enumerate(property_value.values()): - if blender_component.bl_rna.properties[property_name].type == 'FLOAT': - subproperty_value = float(subproperty_value) - print(f"{property_name}[{x}] = {subproperty_value}") blender_subcomponent[x] = subproperty_value @@ -115,11 +114,8 @@ def patched_BlenderNode_create_object(gltf, vnode_id): getattr(blender_component, property_name)[x] = value else: - if blender_component.bl_rna.properties[property_name].type == 'FLOAT': - property_value = float(property_value) - print(f"{property_name} = {property_value}") - blender_component[property_name] = property_value + setattr(blender_component, property_name, property_value) except Exception: print("Error encountered while adding Hubs components:") From c3170847e26e91245e22905e40b6fb58f32632a7 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Fri, 3 Dec 2021 03:46:15 -0500 Subject: [PATCH 04/43] Add support for material components and start on reworking how components are loaded. kit-alt-materials still not fully supported. --- __init__.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 54ec5d44..2913c1d6 100644 --- a/__init__.py +++ b/__init__.py @@ -32,8 +32,14 @@ def get_version_string(): from io_scene_gltf2.blender.exp import gltf2_blender_export from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode +from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial +from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene orig_gather_gltf = gltf2_blender_export.__gather_gltf orig_BlenderNode_create_object = BlenderNode.create_object +orig_BlenderMaterial_create = BlenderMaterial.create +orig_BlenderScene_create = BlenderScene.create + +stored_components = {'object': {}, 'material': {}} def patched_gather_gltf(exporter, export_settings): orig_gather_gltf(exporter, export_settings) @@ -43,6 +49,7 @@ def patched_gather_gltf(exporter, export_settings): @staticmethod def patched_BlenderNode_create_object(gltf, vnode_id): #print("loading hubs components") + orig_active_obj = bpy.context.view_layer.objects.active obj = orig_BlenderNode_create_object(gltf, vnode_id) vnode = gltf.vnodes[vnode_id] @@ -60,6 +67,7 @@ def patched_BlenderNode_create_object(gltf, vnode_id): #print(f"node is: {node}") if node is not None: + print(dir(node)) extensions = node.extensions #print(f"extensions are: {extensions}") if extensions: @@ -77,22 +85,56 @@ def patched_BlenderNode_create_object(gltf, vnode_id): bpy.context.view_layer.objects.active = obj try: + # ADD MAIN HUBS COMPONENT bpy.ops.wm.add_hubs_component(object_source="object", component_name=glb_component_name) blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") + # AUDIO TARGET HUBS COMPONENT BEGIN if glb_component_name == 'audio-target': for property_name, property_value in glb_component_value.items(): if property_name == 'srcNode': - setattr(blender_component, property_name, bpy.data.objects[gltf.vnodes[property_value['index']].name]) + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) else: print(f"{property_name} = {property_value}") setattr(blender_component, property_name, property_value) + # AUDIO TARGET HUBS COMPONENT END + # KIT ALT MATERIALS BEGIN elif glb_component_name == 'kit-alt-materials': - pass + #print(gltf.data.materials[0].name) + for property_name, property_value in glb_component_value.items(): + + # DEFAULT MATERIALS BEGIN + if property_name == 'defaultMaterials': + for x, glb_defaultMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(path="object.hubs_component_kit_alt_materials.defaultMaterials") + + for subproperty_name, subproperty_value in glb_defaultMaterial.items(): + if subproperty_name == 'material': + setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) + + else: + setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) + # DEFAULT MATERIALS END + + # ALT MATERIALS BEGIN + elif property_name == 'altMaterials': + for x, glb_altMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(path="object.hubs_component_kit_alt_materials.altMaterials") + altMaterial_component = blender_component.altMaterials[x] + + for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): + bpy.ops.wm.add_hubs_component_item(path=f"object.hubs_component_kit_alt_materials.altMaterials.{y}.value") + altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] + + else: + setattr(blender_component, property_name, property_value) + # ALT MATERIALS END + + # KIT ALT MATERIALS END else: for property_name, property_value in glb_component_value.items(): @@ -122,11 +164,96 @@ def patched_BlenderNode_create_object(gltf, vnode_id): traceback.print_exc() print("Continuing on....\n") + bpy.context.view_layer.objects.active = orig_active_obj + return obj +@staticmethod +def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): + orig_BlenderMaterial_create(gltf, material_idx, vertex_color) + + glb_material = gltf.data.materials[material_idx] + + if glb_material is not None: + extensions = glb_material.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['material'][glb_material.name] = glb_material + +@staticmethod +def patched_BlenderScene_create(gltf): + orig_BlenderScene_create(gltf) + #orig_active_obj = bpy.context.view_layer.objects.active + + + for glb_material in stored_components['material'].values(): + MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] + + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") + + # ADD MAIN HUBS COMPONENT + material = bpy.data.materials[glb_material.blender_material[None]] + #material_obj = [obj for obj in bpy.data.objects if material.name in obj.material_slots][0] + #material_obj.active_material_index = [idx for idx, mat in enumerate(material_obj.material_slots) if mat.name == material.name][0] + + #bpy.context.view_layer.objects.active = material_obj + #orig_material_obj_sel_state = material_obj.select_get() + #material_obj.select_set(True) + + #orig_active_material_index = material_obj.active_material_index + + + context_override = bpy.context.copy() + #area = [area for area in bpy.context.screen.areas if area.type == "PROPERTIES"][0] + + #context_override['window'] = bpy.context.window + #context_override['screen'] = bpy.context.screen + #context_override['blend_data'] = bpy.context.blend_data + #context_override['annotation_data_owner'] = None + #context_override['area'] = area + #context_override['scene'] = bpy.context.scene + context_override['material'] = material + #context_override['region'] = area.regions[1] + #context_override['space_data'] = area.spaces.active + #context_override['space_data'].context = 'MATERIAL' + #context_override['region'] = area.regions[-1] + + + + bpy.ops.wm.add_hubs_component(context_override, object_source="material", component_name=glb_component_name) + + blender_component = getattr(material, f"hubs_component_{glb_component_name.replace('-', '_')}") + + try: + if glb_component_name == 'video-texture-target': + for property_name, property_value in glb_component_value.items(): + + if property_name == 'srcNode': + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + + #space_data.context = orig_space_data_context + #material_obj.active_material_index = orig_active_material_index + #material_obj.select_set(orig_material_obj_sel_state) + + #bpy.context.view_layer.objects.active = orig_active_obj + def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf BlenderNode.create_object = patched_BlenderNode_create_object + BlenderMaterial.create = patched_BlenderMaterial_create + BlenderScene.create = patched_BlenderScene_create components.register() @@ -138,6 +265,8 @@ def register(): def unregister(): gltf2_blender_export.__gather_gltf = orig_gather_gltf BlenderNode.create_object = orig_BlenderNode_create_object + BlenderMaterial.create = orig_BlenderMaterial_create + BlenderScene.create = orig_BlenderScene_create components.unregister() settings.unregister() From d5ad39902ba2e3a83a9e0492f2ae8aca54a7b3e0 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Mon, 24 Jan 2022 04:42:55 -0500 Subject: [PATCH 05/43] Finished reworking how components are loaded. kit-alt-materials fully supported. --- __init__.py | 225 +++++++++++++++++++++++----------------------------- 1 file changed, 101 insertions(+), 124 deletions(-) diff --git a/__init__.py b/__init__.py index 2913c1d6..5c13e8c6 100644 --- a/__init__.py +++ b/__init__.py @@ -48,8 +48,6 @@ def patched_gather_gltf(exporter, export_settings): @staticmethod def patched_BlenderNode_create_object(gltf, vnode_id): - #print("loading hubs components") - orig_active_obj = bpy.context.view_layer.objects.active obj = orig_BlenderNode_create_object(gltf, vnode_id) vnode = gltf.vnodes[vnode_id] @@ -65,128 +63,135 @@ def patched_BlenderNode_create_object(gltf, vnode_id): node = [n for n in gltf.data.nodes if n.name == vnode.name][0] - #print(f"node is: {node}") if node is not None: - print(dir(node)) extensions = node.extensions - #print(f"extensions are: {extensions}") if extensions: MOZ_hubs_components = extensions.get('MOZ_hubs_components') - #print(f"MOZ_hubs_components are: {MOZ_hubs_components}") if MOZ_hubs_components: - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - if glb_component_name == 'networked': - return + stored_components['object'][node.name] = (vnode, node) - print(f"Node Name: {node.name}") - print(f"Object: {obj}") - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - bpy.context.view_layer.objects.active = obj + return obj - try: - # ADD MAIN HUBS COMPONENT - bpy.ops.wm.add_hubs_component(object_source="object", component_name=glb_component_name) +@staticmethod +def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): + orig_BlenderMaterial_create(gltf, material_idx, vertex_color) - blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") + glb_material = gltf.data.materials[material_idx] - # AUDIO TARGET HUBS COMPONENT BEGIN - if glb_component_name == 'audio-target': - for property_name, property_value in glb_component_value.items(): + if glb_material is not None: + extensions = glb_material.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['material'][glb_material.name] = glb_material - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) +@staticmethod +def patched_BlenderScene_create(gltf): + orig_BlenderScene_create(gltf) + create_object_components(gltf) + create_material_components(gltf) - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - # AUDIO TARGET HUBS COMPONENT END - # KIT ALT MATERIALS BEGIN - elif glb_component_name == 'kit-alt-materials': - #print(gltf.data.materials[0].name) - for property_name, property_value in glb_component_value.items(): - # DEFAULT MATERIALS BEGIN - if property_name == 'defaultMaterials': - for x, glb_defaultMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(path="object.hubs_component_kit_alt_materials.defaultMaterials") +def create_object_components(gltf): + for vnode, node in stored_components['object'].values(): + MOZ_hubs_components = node.extensions['MOZ_hubs_components'] + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + if glb_component_name == 'networked': + continue - for subproperty_name, subproperty_value in glb_defaultMaterial.items(): - if subproperty_name == 'material': - setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) + try: + # ADD MAIN HUBS COMPONENT + obj = vnode.blender_object - else: - setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) - # DEFAULT MATERIALS END + print(f"Node Name: {node.name}") + print(f"Object: {obj}") + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") - # ALT MATERIALS BEGIN - elif property_name == 'altMaterials': - for x, glb_altMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(path="object.hubs_component_kit_alt_materials.altMaterials") - altMaterial_component = blender_component.altMaterials[x] + context_override = bpy.context.copy() + context_override['object'] = obj - for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): - bpy.ops.wm.add_hubs_component_item(path=f"object.hubs_component_kit_alt_materials.altMaterials.{y}.value") - altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] + bpy.ops.wm.add_hubs_component(context_override, object_source="object", component_name=glb_component_name) - else: - setattr(blender_component, property_name, property_value) - # ALT MATERIALS END + blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") - # KIT ALT MATERIALS END + # AUDIO TARGET HUBS COMPONENT BEGIN + if glb_component_name == 'audio-target': + for property_name, property_value in glb_component_value.items(): + + if property_name == 'srcNode': + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) else: - for property_name, property_value in glb_component_value.items(): + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + # AUDIO TARGET HUBS COMPONENT END - if isinstance(property_value, dict): - blender_subcomponent = getattr(blender_component, property_name) - for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") - blender_subcomponent[x] = subproperty_value + # KIT ALT MATERIALS BEGIN + elif glb_component_name == 'kit-alt-materials': + #print(gltf.data.materials[0].name) + for property_name, property_value in glb_component_value.items(): - else: - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) + # DEFAULT MATERIALS BEGIN + if property_name == 'defaultMaterials': + for x, glb_defaultMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.defaultMaterials") - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value + for subproperty_name, subproperty_value in glb_defaultMaterial.items(): + if subproperty_name == 'material': + setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) + setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) + # DEFAULT MATERIALS END - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") + # ALT MATERIALS BEGIN + elif property_name == 'altMaterials': + for x, glb_altMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.altMaterials") + altMaterial_component = blender_component.altMaterials[x] - bpy.context.view_layer.objects.active = orig_active_obj + for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): + bpy.ops.wm.add_hubs_component_item(context_override, path=f"object.hubs_component_kit_alt_materials.altMaterials.0.value") + altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] - return obj + else: + setattr(blender_component, property_name, property_value) + # ALT MATERIALS END -@staticmethod -def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): - orig_BlenderMaterial_create(gltf, material_idx, vertex_color) + # KIT ALT MATERIALS END - glb_material = gltf.data.materials[material_idx] + else: + for property_name, property_value in glb_component_value.items(): - if glb_material is not None: - extensions = glb_material.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['material'][glb_material.name] = glb_material + if isinstance(property_value, dict): + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value -@staticmethod -def patched_BlenderScene_create(gltf): - orig_BlenderScene_create(gltf) - #orig_active_obj = bpy.context.view_layer.objects.active + else: + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + +def create_material_components(gltf): for glb_material in stored_components['material'].values(): MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] @@ -194,40 +199,18 @@ def patched_BlenderScene_create(gltf): print(f"Hubs Component Name: {glb_component_name}") print(f"Hubs Component Value: {glb_component_value}") - # ADD MAIN HUBS COMPONENT - material = bpy.data.materials[glb_material.blender_material[None]] - #material_obj = [obj for obj in bpy.data.objects if material.name in obj.material_slots][0] - #material_obj.active_material_index = [idx for idx, mat in enumerate(material_obj.material_slots) if mat.name == material.name][0] - - #bpy.context.view_layer.objects.active = material_obj - #orig_material_obj_sel_state = material_obj.select_get() - #material_obj.select_set(True) - - #orig_active_material_index = material_obj.active_material_index - - - context_override = bpy.context.copy() - #area = [area for area in bpy.context.screen.areas if area.type == "PROPERTIES"][0] - - #context_override['window'] = bpy.context.window - #context_override['screen'] = bpy.context.screen - #context_override['blend_data'] = bpy.context.blend_data - #context_override['annotation_data_owner'] = None - #context_override['area'] = area - #context_override['scene'] = bpy.context.scene - context_override['material'] = material - #context_override['region'] = area.regions[1] - #context_override['space_data'] = area.spaces.active - #context_override['space_data'].context = 'MATERIAL' - #context_override['region'] = area.regions[-1] + try: + # ADD MAIN HUBS COMPONENT + material = bpy.data.materials[glb_material.blender_material[None]] + context_override = bpy.context.copy() + context_override['material'] = material + bpy.ops.wm.add_hubs_component(context_override, object_source="material", component_name=glb_component_name) - bpy.ops.wm.add_hubs_component(context_override, object_source="material", component_name=glb_component_name) + blender_component = getattr(material, f"hubs_component_{glb_component_name.replace('-', '_')}") - blender_component = getattr(material, f"hubs_component_{glb_component_name.replace('-', '_')}") - try: if glb_component_name == 'video-texture-target': for property_name, property_value in glb_component_value.items(): @@ -243,12 +226,6 @@ def patched_BlenderScene_create(gltf): traceback.print_exc() print("Continuing on....\n") - #space_data.context = orig_space_data_context - #material_obj.active_material_index = orig_active_material_index - #material_obj.select_set(orig_material_obj_sel_state) - - #bpy.context.view_layer.objects.active = orig_active_obj - def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf BlenderNode.create_object = patched_BlenderNode_create_object From 2ed37b87a30e04b9a2b8525a5cfa7d284538e87a Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Mon, 24 Jan 2022 18:09:16 -0500 Subject: [PATCH 06/43] Add support for importing scene properties. --- __init__.py | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 5c13e8c6..75c541f0 100644 --- a/__init__.py +++ b/__init__.py @@ -34,6 +34,7 @@ def get_version_string(): from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene +from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage orig_gather_gltf = gltf2_blender_export.__gather_gltf orig_BlenderNode_create_object = BlenderNode.create_object orig_BlenderMaterial_create = BlenderMaterial.create @@ -90,8 +91,7 @@ def patched_BlenderScene_create(gltf): orig_BlenderScene_create(gltf) create_object_components(gltf) create_material_components(gltf) - - + create_scene_components(gltf) def create_object_components(gltf): for vnode, node in stored_components['object'].values(): @@ -226,6 +226,67 @@ def create_material_components(gltf): traceback.print_exc() print("Continuing on....\n") +def create_scene_components(gltf): + if gltf.data.scene is None: + return + + gltf_scene = gltf.data.scenes[gltf.data.scene] + extensions = gltf_scene.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + enviro_imgs = {} + + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") + + if glb_component_name == "environment-settings": + + for gltf_texture in gltf.data.textures: + extensions = gltf_texture.extensions + if extensions: + MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') + if MOZ_texture_rgbe: + BlenderImage.create(gltf, MOZ_texture_rgbe['source']) + pyimg = gltf.data.images[MOZ_texture_rgbe['source']] + blender_image_name = pyimg.blender_image_name + enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name + + + try: + # ADD MAIN HUBS COMPONENT + scene = bpy.data.scenes[gltf.blender_scene] + bpy.ops.wm.add_hubs_component(object_source="scene", component_name=glb_component_name) + blender_component = getattr(scene, f"hubs_component_{glb_component_name.replace('-', '_')}") + + for property_name, property_value in glb_component_value.items(): + + if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": + blender_image_name = enviro_imgs[property_value['index']] + blender_image = bpy.data.images[blender_image_name] + + setattr(blender_component, property_name, blender_image) + + else: + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf BlenderNode.create_object = patched_BlenderNode_create_object From df211d245a000d1aabd6d28c68a581476e108b2f Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Wed, 6 Apr 2022 04:15:33 -0400 Subject: [PATCH 07/43] Separate import functions out into their own file. Refactor how special cases are handled. Reduce code duplication. --- __init__.py | 257 +------------------------------------------ importer.py | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+), 254 deletions(-) create mode 100644 importer.py diff --git a/__init__.py b/__init__.py index 51ef5934..8ec85311 100644 --- a/__init__.py +++ b/__init__.py @@ -1,13 +1,12 @@ import bpy import uuid -import traceback -import re from . import settings from . import components from . import operators from . import panels from . import nodes +from . import importer from .gather_properties import gather_properties, gather_lightmap_texture_info bl_info = { @@ -36,281 +35,31 @@ def get_version_string(): from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage orig_gather_gltf = gltf2_blender_export.__gather_gltf -orig_BlenderNode_create_object = BlenderNode.create_object -orig_BlenderMaterial_create = BlenderMaterial.create -orig_BlenderScene_create = BlenderScene.create - -stored_components = {'object': {}, 'material': {}} def patched_gather_gltf(exporter, export_settings): orig_gather_gltf(exporter, export_settings) export_user_extensions('hubs_gather_gltf_hook', export_settings, exporter._GlTF2Exporter__gltf) exporter._GlTF2Exporter__traverse(exporter._GlTF2Exporter__gltf.extensions) -@staticmethod -def patched_BlenderNode_create_object(gltf, vnode_id): - obj = orig_BlenderNode_create_object(gltf, vnode_id) - - vnode = gltf.vnodes[vnode_id] - node = None - - if vnode.camera_node_idx is not None: - parent_vnode = gltf.vnodes[vnode.parent] - if parent_vnode.name: - node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] - - else: - if vnode.name: - node = [n for n in gltf.data.nodes if n.name == vnode.name][0] - - - if node is not None: - extensions = node.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['object'][node.name] = (vnode, node) - - return obj - -@staticmethod -def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): - orig_BlenderMaterial_create(gltf, material_idx, vertex_color) - - glb_material = gltf.data.materials[material_idx] - - if glb_material is not None: - extensions = glb_material.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['material'][glb_material.name] = glb_material - -@staticmethod -def patched_BlenderScene_create(gltf): - orig_BlenderScene_create(gltf) - create_object_components(gltf) - create_material_components(gltf) - create_scene_components(gltf) - -def create_object_components(gltf): - for vnode, node in stored_components['object'].values(): - MOZ_hubs_components = node.extensions['MOZ_hubs_components'] - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - if glb_component_name == 'networked': - continue - - try: - # ADD MAIN HUBS COMPONENT - obj = vnode.blender_object - - print(f"Node Name: {node.name}") - print(f"Object: {obj}") - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - - context_override = bpy.context.copy() - context_override['object'] = obj - - bpy.ops.wm.add_hubs_component(context_override, object_source="object", component_name=glb_component_name) - - blender_component = getattr(obj, f"hubs_component_{glb_component_name.replace('-', '_')}") - - # AUDIO TARGET HUBS COMPONENT BEGIN - if glb_component_name == 'audio-target': - for property_name, property_value in glb_component_value.items(): - - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - # AUDIO TARGET HUBS COMPONENT END - - # KIT ALT MATERIALS BEGIN - elif glb_component_name == 'kit-alt-materials': - #print(gltf.data.materials[0].name) - for property_name, property_value in glb_component_value.items(): - - # DEFAULT MATERIALS BEGIN - if property_name == 'defaultMaterials': - for x, glb_defaultMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.defaultMaterials") - - for subproperty_name, subproperty_value in glb_defaultMaterial.items(): - if subproperty_name == 'material': - setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) - - else: - setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) - # DEFAULT MATERIALS END - - # ALT MATERIALS BEGIN - elif property_name == 'altMaterials': - for x, glb_altMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.altMaterials") - altMaterial_component = blender_component.altMaterials[x] - - for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): - bpy.ops.wm.add_hubs_component_item(context_override, path=f"object.hubs_component_kit_alt_materials.altMaterials.0.value") - altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] - - else: - setattr(blender_component, property_name, property_value) - # ALT MATERIALS END - - # KIT ALT MATERIALS END - - else: - for property_name, property_value in glb_component_value.items(): - - if isinstance(property_value, dict): - blender_subcomponent = getattr(blender_component, property_name) - for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") - blender_subcomponent[x] = subproperty_value - - else: - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) - - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - - -def create_material_components(gltf): - for glb_material in stored_components['material'].values(): - MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] - - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - - try: - # ADD MAIN HUBS COMPONENT - material = bpy.data.materials[glb_material.blender_material[None]] - - context_override = bpy.context.copy() - context_override['material'] = material - - bpy.ops.wm.add_hubs_component(context_override, object_source="material", component_name=glb_component_name) - - blender_component = getattr(material, f"hubs_component_{glb_component_name.replace('-', '_')}") - - - if glb_component_name == 'video-texture-target': - for property_name, property_value in glb_component_value.items(): - - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - -def create_scene_components(gltf): - if gltf.data.scene is None: - return - - gltf_scene = gltf.data.scenes[gltf.data.scene] - extensions = gltf_scene.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - enviro_imgs = {} - - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - - if glb_component_name == "environment-settings": - - for gltf_texture in gltf.data.textures: - extensions = gltf_texture.extensions - if extensions: - MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') - if MOZ_texture_rgbe: - BlenderImage.create(gltf, MOZ_texture_rgbe['source']) - pyimg = gltf.data.images[MOZ_texture_rgbe['source']] - blender_image_name = pyimg.blender_image_name - enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name - - - try: - # ADD MAIN HUBS COMPONENT - scene = bpy.data.scenes[gltf.blender_scene] - bpy.ops.wm.add_hubs_component(object_source="scene", component_name=glb_component_name) - blender_component = getattr(scene, f"hubs_component_{glb_component_name.replace('-', '_')}") - - for property_name, property_value in glb_component_value.items(): - - if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": - blender_image_name = enviro_imgs[property_value['index']] - blender_image = bpy.data.images[blender_image_name] - - setattr(blender_component, property_name, blender_image) - - else: - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) - - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf - BlenderNode.create_object = patched_BlenderNode_create_object - BlenderMaterial.create = patched_BlenderMaterial_create - BlenderScene.create = patched_BlenderScene_create - components.register() settings.register() operators.register() panels.register() nodes.register() + importer.register() def unregister(): gltf2_blender_export.__gather_gltf = orig_gather_gltf - BlenderNode.create_object = orig_BlenderNode_create_object - BlenderMaterial.create = orig_BlenderMaterial_create - BlenderScene.create = orig_BlenderScene_create components.unregister() settings.unregister() operators.unregister() panels.unregister() nodes.unregister() + importer.unregister() unregister_export_panel() diff --git a/importer.py b/importer.py new file mode 100644 index 00000000..7859d0bc --- /dev/null +++ b/importer.py @@ -0,0 +1,308 @@ +import bpy +import traceback +import re +from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode +from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial +from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene +from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage + +# import hooks are not present, make a custom hook for now +# ideally we can resolve this upstream somehow https://github.com/KhronosGroup/glTF-Blender-IO +orig_BlenderNode_create_object = BlenderNode.create_object +orig_BlenderMaterial_create = BlenderMaterial.create +orig_BlenderScene_create = BlenderScene.create + +stored_components = {'object': {}, 'material': {}} + +@staticmethod +def patched_BlenderNode_create_object(gltf, vnode_id): + obj = orig_BlenderNode_create_object(gltf, vnode_id) + + vnode = gltf.vnodes[vnode_id] + node = None + + if vnode.camera_node_idx is not None: + parent_vnode = gltf.vnodes[vnode.parent] + if parent_vnode.name: + node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] + + else: + if vnode.name: + node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + + + if node is not None: + extensions = node.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['object'][node.name] = (vnode, node) + + return obj + +@staticmethod +def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): + orig_BlenderMaterial_create(gltf, material_idx, vertex_color) + + glb_material = gltf.data.materials[material_idx] + + if glb_material is not None: + extensions = glb_material.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['material'][glb_material.name] = glb_material + +@staticmethod +def patched_BlenderScene_create(gltf): + orig_BlenderScene_create(gltf) + + create_object_hubs_components(gltf) + create_material_hubs_components(gltf) + create_scene_hubs_components(gltf) + + +def create_object_hubs_components(gltf): + special_cases = { + 'networked': handle_networked, + 'audio-target': handle_audio_target, + 'kit-alt-materials': handle_kit_alt_materials, + } + + for vnode, node in stored_components['object'].values(): + MOZ_hubs_components = node.extensions['MOZ_hubs_components'] + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name](gltf, vnode, node, glb_component_name, glb_component_value) + continue + + else: + blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if isinstance(property_value, dict): + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value + + else: + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + +def create_material_hubs_components(gltf): + special_cases = { + 'video-texture-target': handle_video_texture_target, + } + + for glb_material in stored_components['material'].values(): + MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] + + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name](gltf, glb_material, glb_component_name, glb_component_value) + continue + + else: + blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) + + for property_name, property_value in glb_component_value.items(): + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + +def create_scene_hubs_components(gltf): + if gltf.data.scene is None: + return + + special_cases = { + 'environment-settings': handle_environment_settings, + } + + gltf_scene = gltf.data.scenes[gltf.data.scene] + extensions = gltf_scene.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name](gltf, glb_component_name, glb_component_value) + continue + + blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) + + for property_name, property_value in glb_component_value.items(): + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + +# OBJECT SPECIAL CASES +def handle_networked(gltf, vnode, node, glb_component_name, glb_component_value): + return + +def handle_audio_target(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + +def handle_kit_alt_materials(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'defaultMaterials': + for x, glb_defaultMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.defaultMaterials") + + for subproperty_name, subproperty_value in glb_defaultMaterial.items(): + if subproperty_name == 'material': + setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) + + else: + setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) + + elif property_name == 'altMaterials': + for x, glb_altMaterial in enumerate(property_value): + bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.altMaterials") + altMaterial_component = blender_component.altMaterials[x] + + for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): + bpy.ops.wm.add_hubs_component_item(context_override, path=f"object.hubs_component_kit_alt_materials.altMaterials.0.value") + altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] + + else: + setattr(blender_component, property_name, property_value) + +# MATERIAL SPECIAL CASES +def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): + blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + +# SCENE SPECIAL CASES +def handle_environment_settings(gltf, glb_component_name, glb_component_value): + blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) + + # load environment maps + enviro_imgs = {} + for gltf_texture in gltf.data.textures: + extensions = gltf_texture.extensions + if extensions: + MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') + if MOZ_texture_rgbe: + BlenderImage.create(gltf, MOZ_texture_rgbe['source']) + pyimg = gltf.data.images[MOZ_texture_rgbe['source']] + blender_image_name = pyimg.blender_image_name + enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name + + + for property_name, property_value in glb_component_value.items(): + if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": + blender_image_name = enviro_imgs[property_value['index']] + blender_image = bpy.data.images[blender_image_name] + + setattr(blender_component, property_name, blender_image) + + else: + if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + hexcolor = property_value.lstrip('#') + rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) + rgb_float = tuple((i/255 for i in rgb_int)) + + for x, value in enumerate(rgb_float): + print(f"{property_name}[{x}] = {value}") + getattr(blender_component, property_name)[x] = value + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + +def add_hubs_component(element_type, glb_component_name, glb_component_value, vnode=None, node=None, glb_material=None, gltf=None): + # get element + if element_type == "object": + element = vnode.blender_object + + elif element_type == "material": + element = bpy.data.materials[glb_material.blender_material[None]] + + elif element_type == "scene": + element = bpy.data.scenes[gltf.blender_scene] + + else: + element = None + + # print debug info + if element_type == "object": + print(f"Node Name: {node.name}") + print(f"Object: {element}") + + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") + + + # override context + context_override = bpy.context.copy() + context_override[element_type] = element + + # create component + bpy.ops.wm.add_hubs_component(context_override, object_source=element_type, component_name=glb_component_name) + + return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") + +def register(): + BlenderNode.create_object = patched_BlenderNode_create_object + BlenderMaterial.create = patched_BlenderMaterial_create + BlenderScene.create = patched_BlenderScene_create + +def unregister(): + BlenderNode.create_object = orig_BlenderNode_create_object + BlenderMaterial.create = orig_BlenderMaterial_create + BlenderScene.create = orig_BlenderScene_create From 889181f020ae7bc4c8f76561318ef866a61d6742 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 12 May 2022 20:01:23 -0400 Subject: [PATCH 08/43] Fix setting colors from Hex, handle more special cases, reduce code duplication. --- importer.py | 132 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 45 deletions(-) diff --git a/importer.py b/importer.py index 7859d0bc..bae77772 100644 --- a/importer.py +++ b/importer.py @@ -65,8 +65,14 @@ def patched_BlenderScene_create(gltf): def create_object_hubs_components(gltf): special_cases = { 'networked': handle_networked, - 'audio-target': handle_audio_target, + #'audio-target': handle_audio_target, 'kit-alt-materials': handle_kit_alt_materials, + 'spawn-point': handle_spawn_point, + 'heightfield': handle_heightfield, + 'box-collider': handle_box_collider, + 'scene-preview-camera': handle_scene_preview_camera, + 'trimesh': handle_trimesh, + 'spawner': handle_spawner, } for vnode, node in stored_components['object'].values(): @@ -81,25 +87,7 @@ def create_object_hubs_components(gltf): blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) for property_name, property_value in glb_component_value.items(): - if isinstance(property_value, dict): - blender_subcomponent = getattr(blender_component, property_name) - for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") - blender_subcomponent[x] = subproperty_value - - else: - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) - - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) + assign_property(gltf, blender_component, property_name, property_value) except Exception: print("Error encountered while adding Hubs components:") @@ -108,7 +96,7 @@ def create_object_hubs_components(gltf): def create_material_hubs_components(gltf): special_cases = { - 'video-texture-target': handle_video_texture_target, + #'video-texture-target': handle_video_texture_target, } for glb_material in stored_components['material'].values(): @@ -124,8 +112,7 @@ def create_material_hubs_components(gltf): blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) for property_name, property_value in glb_component_value.items(): - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) + assign_property(gltf, blender_component, property_name, property_value) except Exception: @@ -139,6 +126,7 @@ def create_scene_hubs_components(gltf): special_cases = { 'environment-settings': handle_environment_settings, + 'background': handle_background, } gltf_scene = gltf.data.scenes[gltf.data.scene] @@ -155,24 +143,14 @@ def create_scene_hubs_components(gltf): blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) for property_name, property_value in glb_component_value.items(): - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) - - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) + assign_property(gltf, blender_component, property_name, property_value) except Exception: print("Error encountered while adding Hubs components:") traceback.print_exc() print("Continuing on....\n") + # OBJECT SPECIAL CASES def handle_networked(gltf, vnode, node, glb_component_name, glb_component_value): return @@ -215,6 +193,36 @@ def handle_kit_alt_materials(gltf, vnode, node, glb_component_name, glb_componen else: setattr(blender_component, property_name, property_value) +def handle_spawn_point(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", "waypoint", glb_component_value, vnode=vnode, node=node) + + blender_component.canBeSpawnPoint = True + +def handle_heightfield(gltf, vnode, node, glb_component_name, glb_component_value): + return + +def handle_box_collider(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", "ammo-shape", glb_component_value, vnode=vnode, node=node) + + blender_component.type = "box" + +def handle_scene_preview_camera(gltf, vnode, node, glb_component_name, glb_component_value): + return + +def handle_trimesh(gltf, vnode, node, glb_component_name, glb_component_value): + return + +def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'mediaOptions': + setattr(getattr(blender_component, property_name), "applyGravity", property_value["applyGravity"]) + + else: + assign_property(gltf, blender_component, property_name, property_value) + + # MATERIAL SPECIAL CASES def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) @@ -227,6 +235,7 @@ def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_comp print(f"{property_name} = {property_value}") setattr(blender_component, property_name, property_value) + # SCENE SPECIAL CASES def handle_environment_settings(gltf, glb_component_name, glb_component_value): blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) @@ -252,19 +261,17 @@ def handle_environment_settings(gltf, glb_component_name, glb_component_value): setattr(blender_component, property_name, blender_image) else: - if re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - hexcolor = property_value.lstrip('#') - rgb_int = tuple(int(hexcolor[i:i+2], 16) for i in (0, 2, 4)) - rgb_float = tuple((i/255 for i in rgb_int)) + assign_property(gltf, blender_component, property_name, property_value) + +def handle_background(gltf, glb_component_name, glb_component_value): + blender_component = add_hubs_component("scene", "environment-settings", glb_component_value, gltf=gltf) + + blender_component.toneMapping = "LinearToneMapping" - for x, value in enumerate(rgb_float): - print(f"{property_name}[{x}] = {value}") - getattr(blender_component, property_name)[x] = value + set_color_from_hex(blender_component, "backgroundColor", glb_component_value['color']) - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) +# UTILITIES def add_hubs_component(element_type, glb_component_name, glb_component_value, vnode=None, node=None, glb_material=None, gltf=None): # get element if element_type == "object": @@ -297,6 +304,41 @@ def add_hubs_component(element_type, glb_component_name, glb_component_value, vn return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") +def set_color_from_hex(blender_component, property_name, hexcolor): + hexcolor = hexcolor.lstrip('#') + rgb_int = [int(hexcolor[i:i+2], 16) for i in (0, 2, 4)] + + for x, value in enumerate(rgb_int): + rgb_float = value/255 if value > 0 else 0 + + # convert sRGB values to linear + if rgb_float < 0.04045: + rgb_float_linear = rgb_float * (1.0 / 12.92) + + else: + rgb_float_linear = ((rgb_float + 0.055) * (1.0 / 1.055)) ** 2.4 + + print(f"{property_name}[{x}] = {rgb_float_linear}") + getattr(blender_component, property_name)[x] = rgb_float_linear + +def assign_property(gltf, blender_component, property_name, property_value): + if property_name == 'srcNode': + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) + + elif isinstance(property_value, dict): + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value + + elif re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + set_color_from_hex(blender_component, property_name, property_value) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + def register(): BlenderNode.create_object = patched_BlenderNode_create_object BlenderMaterial.create = patched_BlenderMaterial_create From a35f433e2497d0ac65c8644f17e561fe15d3ed3e Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 12 May 2022 20:20:15 -0400 Subject: [PATCH 09/43] Cleanup unused imports. --- __init__.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/__init__.py b/__init__.py index 8ec85311..d7b03bb8 100644 --- a/__init__.py +++ b/__init__.py @@ -30,12 +30,7 @@ def get_version_string(): # ideally we can resolve this upstream somehow https://github.com/KhronosGroup/glTF-Blender-IO/issues/1009 from io_scene_gltf2.blender.exp import gltf2_blender_export from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions -from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode -from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial -from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene -from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage orig_gather_gltf = gltf2_blender_export.__gather_gltf - def patched_gather_gltf(exporter, export_settings): orig_gather_gltf(exporter, export_settings) export_user_extensions('hubs_gather_gltf_hook', export_settings, exporter._GlTF2Exporter__gltf) @@ -44,6 +39,7 @@ def patched_gather_gltf(exporter, export_settings): def register(): gltf2_blender_export.__gather_gltf = patched_gather_gltf + components.register() settings.register() operators.register() From fb29aeeed33438a9250edd10b49dda33e35d414d Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Wed, 6 Jul 2022 00:47:35 -0400 Subject: [PATCH 10/43] Update importer for changes in the new architecture. --- addons/io_hubs_addon/io/gltf_importer.py | 57 +++++++++--------------- 1 file changed, 21 insertions(+), 36 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index bae77772..7c7fea01 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -6,8 +6,10 @@ from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage -# import hooks are not present, make a custom hook for now -# ideally we can resolve this upstream somehow https://github.com/KhronosGroup/glTF-Blender-IO +from ..components.utils import has_component, add_component +from ..components.definitions.loop_animation import has_track + +# import hooks were only recently added to the glTF exporter, so make a custom hook for now orig_BlenderNode_create_object = BlenderNode.create_object orig_BlenderMaterial_create = BlenderMaterial.create orig_BlenderScene_create = BlenderScene.create @@ -66,13 +68,13 @@ def create_object_hubs_components(gltf): special_cases = { 'networked': handle_networked, #'audio-target': handle_audio_target, - 'kit-alt-materials': handle_kit_alt_materials, 'spawn-point': handle_spawn_point, 'heightfield': handle_heightfield, 'box-collider': handle_box_collider, 'scene-preview-camera': handle_scene_preview_camera, 'trimesh': handle_trimesh, 'spawner': handle_spawner, + 'loop-animation': handle_loop_animation, } for vnode, node in stored_components['object'].values(): @@ -166,33 +168,6 @@ def handle_audio_target(gltf, vnode, node, glb_component_name, glb_component_val print(f"{property_name} = {property_value}") setattr(blender_component, property_name, property_value) -def handle_kit_alt_materials(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'defaultMaterials': - for x, glb_defaultMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.defaultMaterials") - - for subproperty_name, subproperty_value in glb_defaultMaterial.items(): - if subproperty_name == 'material': - setattr(blender_component.defaultMaterials[x], 'material', bpy.data.materials[gltf.data.materials[subproperty_value].name]) - - else: - setattr(blender_component.defaultMaterials[x], subproperty_name, subproperty_value) - - elif property_name == 'altMaterials': - for x, glb_altMaterial in enumerate(property_value): - bpy.ops.wm.add_hubs_component_item(context_override, path="object.hubs_component_kit_alt_materials.altMaterials") - altMaterial_component = blender_component.altMaterials[x] - - for y, glb_sub_altMaterial_index in enumerate(glb_altMaterial): - bpy.ops.wm.add_hubs_component_item(context_override, path=f"object.hubs_component_kit_alt_materials.altMaterials.0.value") - altMaterial_component.value[y].value = bpy.data.materials[gltf.data.materials[glb_sub_altMaterial_index].name] - - else: - setattr(blender_component, property_name, property_value) - def handle_spawn_point(gltf, vnode, node, glb_component_name, glb_component_value): blender_component = add_hubs_component("object", "waypoint", glb_component_value, vnode=vnode, node=node) @@ -222,6 +197,20 @@ def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): else: assign_property(gltf, blender_component, property_name, property_value) +def handle_loop_animation(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'clip': + tracks = property_value.split(",") + for track_name in tracks: + if not has_track(blender_component.tracks_list, track_name): + track = blender_component.tracks_list.add() + track.name = track_name.strip() + + else: + assign_property(gltf, blender_component, property_name, property_value) + # MATERIAL SPECIAL CASES def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): @@ -294,13 +283,9 @@ def add_hubs_component(element_type, glb_component_name, glb_component_value, vn print(f"Hubs Component Name: {glb_component_name}") print(f"Hubs Component Value: {glb_component_value}") - - # override context - context_override = bpy.context.copy() - context_override[element_type] = element - # create component - bpy.ops.wm.add_hubs_component(context_override, object_source=element_type, component_name=glb_component_name) + if not has_component(element, glb_component_name): + add_component(element, glb_component_name) return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") From ba9d049149ec43a500adf39ce946b0dc0b7eaa18 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 7 Jul 2022 03:55:15 -0400 Subject: [PATCH 11/43] Clear the stored components after the import is finished so they don't interfere with the next import. --- addons/io_hubs_addon/io/gltf_importer.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 7c7fea01..b28be74d 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -57,12 +57,17 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): @staticmethod def patched_BlenderScene_create(gltf): + global stored_components orig_BlenderScene_create(gltf) create_object_hubs_components(gltf) create_material_hubs_components(gltf) create_scene_hubs_components(gltf) + # clear stored components so as not to conflict with the next import + for key in stored_components.keys(): + stored_components[key].clear() + def create_object_hubs_components(gltf): special_cases = { From c1d17343a2f1a2cc43b726915c959b7a4512ee11 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 7 Jul 2022 04:09:30 -0400 Subject: [PATCH 12/43] Handle properties that link to objects in a more reliable and future proof way. --- addons/io_hubs_addon/io/gltf_importer.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index b28be74d..49a42947 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -312,14 +312,16 @@ def set_color_from_hex(blender_component, property_name, hexcolor): getattr(blender_component, property_name)[x] = rgb_float_linear def assign_property(gltf, blender_component, property_name, property_value): - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - elif isinstance(property_value, dict): - blender_subcomponent = getattr(blender_component, property_name) - for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") - blender_subcomponent[x] = subproperty_value + if isinstance(property_value, dict): + if property_value.get('__mhc_link_type'): + if len(property_value) == 2: + setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) + + else: + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value elif re.fullmatch("#[0-9a-fA-F]*", str(property_value)): set_color_from_hex(blender_component, property_name, property_value) From af86b327e1be84bf66b88eefb025025200af8e65 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Thu, 7 Jul 2022 04:11:54 -0400 Subject: [PATCH 13/43] Update handle_spawner to the new architecture. --- addons/io_hubs_addon/io/gltf_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 49a42947..3388d74e 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -197,7 +197,7 @@ def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): for property_name, property_value in glb_component_value.items(): if property_name == 'mediaOptions': - setattr(getattr(blender_component, property_name), "applyGravity", property_value["applyGravity"]) + setattr(blender_component, "applyGravity", property_value["applyGravity"]) else: assign_property(gltf, blender_component, property_name, property_value) From 6f4a80fbab426eb30a7aca043a6c1398b79c8091 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 28 Jul 2022 14:20:49 +0200 Subject: [PATCH 14/43] Add support for newer import API and refactor some code --- addons/io_hubs_addon/__init__.py | 15 +- .../components/definitions/audio_target.py | 16 +- .../components/definitions/background.py | 19 + .../definitions/environment_settings.py | 37 +- .../components/definitions/loop_animation.py | 18 + .../definitions/video_texture_target.py | 16 +- .../components/hubs_component.py | 12 +- addons/io_hubs_addon/io/gltf_exporter.py | 81 +--- addons/io_hubs_addon/io/gltf_importer.py | 370 +++--------------- .../io_hubs_addon/io/gltf_importer_compat.py | 313 +++++++++++++++ addons/io_hubs_addon/io/panels.py | 121 ++++++ addons/io_hubs_addon/io/utils.py | 86 ++++ 12 files changed, 697 insertions(+), 407 deletions(-) create mode 100644 addons/io_hubs_addon/components/definitions/background.py create mode 100644 addons/io_hubs_addon/io/gltf_importer_compat.py create mode 100644 addons/io_hubs_addon/io/panels.py diff --git a/addons/io_hubs_addon/__init__.py b/addons/io_hubs_addon/__init__.py index 6394013a..8471fed7 100644 --- a/addons/io_hubs_addon/__init__.py +++ b/addons/io_hubs_addon/__init__.py @@ -1,5 +1,11 @@ -from .io import gltf_exporter, gltf_importer from . import (nodes, components) +from .io import gltf_exporter, panels +import bpy +if bpy.app.version < (3, 0, 0): + from .io import gltf_importer_compat as gltf_importer +else: + from .io import gltf_importer + bl_info = { "name": "Hubs Blender Addon", "author": "Mozilla Hubs", @@ -16,6 +22,7 @@ def register(): + panels.register() gltf_exporter.register() gltf_importer.register() nodes.register() @@ -27,6 +34,7 @@ def unregister(): nodes.unregister() gltf_importer.unregister() gltf_exporter.unregister() + panels.unregister() # called by gltf-blender-io after it has loaded @@ -36,6 +44,9 @@ def unregister(): glTF2_pre_export_callback = gltf_exporter.glTF2_pre_export_callback glTF2_post_export_callback = gltf_exporter.glTF2_post_export_callback +if bpy.app.version > (3, 0, 0): + glTF2ImportUserExtension = gltf_importer.glTF2ImportUserExtension + def register_panel(): - return gltf_exporter.register_export_panel() + return panels.register_panels() diff --git a/addons/io_hubs_addon/components/definitions/audio_target.py b/addons/io_hubs_addon/components/definitions/audio_target.py index c5000855..75a4c7c9 100644 --- a/addons/io_hubs_addon/components/definitions/audio_target.py +++ b/addons/io_hubs_addon/components/definitions/audio_target.py @@ -4,7 +4,7 @@ from ..utils import has_component from ..types import Category, PanelType, NodeType from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property +from ...io.utils import gather_joint_property, gather_node_property, add_hubs_import_component BLANK_ID = "374e54CMHFCipSk" @@ -159,3 +159,17 @@ def gather(self, export_settings, object): 'minDelay': self.minDelay, 'debug': self.debug } + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = add_hubs_import_component( + component_name, blender_object) + + for property_name, property_value in component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, + import_settings.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/background.py b/addons/io_hubs_addon/components/definitions/background.py new file mode 100644 index 00000000..00402fcf --- /dev/null +++ b/addons/io_hubs_addon/components/definitions/background.py @@ -0,0 +1,19 @@ +from ...io.utils import add_hubs_import_component, assign_property +from ..hubs_component import HubsComponent +from ..types import NodeType + + +class EnvironmentSettings(HubsComponent): + _definition = { + 'name': 'background', + 'display_name': 'Background', + 'node_type': NodeType.SCENE + } + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = add_hubs_import_component( + 'environemnt-settings', blender_object) + for property_name, property_value in component_value.items(): + assign_property(import_settings.vnodes, blender_component, + property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/environment_settings.py b/addons/io_hubs_addon/components/definitions/environment_settings.py index 5e73c394..2f0355aa 100644 --- a/addons/io_hubs_addon/components/definitions/environment_settings.py +++ b/addons/io_hubs_addon/components/definitions/environment_settings.py @@ -1,8 +1,10 @@ from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, PointerProperty from bpy.types import Image -from ...io.utils import gather_texture_property, gather_color_property +from ...io.utils import add_hubs_import_component, assign_property, gather_texture_property, gather_color_property from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType +import bpy +from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage TOME_MAPPING = [("NoToneMapping", "None", "No tone mapping."), @@ -70,3 +72,36 @@ def gather(self, export_settings, object): self, 'envMapTexture') } + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = add_hubs_import_component( + component_name, blender_object) + + images = {} + for gltf_texture in import_settings.data.textures: + extensions = gltf_texture.extensions + source = None + if extensions: + MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') + if MOZ_texture_rgbe: + source = MOZ_texture_rgbe['source'] + else: + source = gltf_texture.source + + if source is not None and source not in import_settings.data.images: + BlenderImage.create( + import_settings, source) + pyimg = import_settings.data.images[source] + blender_image_name = pyimg.blender_image_name + images[source] = blender_image_name + + for property_name, property_value in component_value.items(): + if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": + blender_image_name = images[property_value['index']] + blender_image = bpy.data.images[blender_image_name] + setattr(blender_component, property_name, blender_image) + + else: + assign_property(import_settings.vnodes, blender_component, + property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/loop_animation.py b/addons/io_hubs_addon/components/definitions/loop_animation.py index 57079d8e..27037805 100644 --- a/addons/io_hubs_addon/components/definitions/loop_animation.py +++ b/addons/io_hubs_addon/components/definitions/loop_animation.py @@ -4,6 +4,7 @@ from bpy.types import PropertyGroup, Menu, Operator from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType +from ...io.utils import add_hubs_import_component, assign_property class TracksList(bpy.types.UIList): @@ -198,3 +199,20 @@ def migrate_data(ob): if ob.type == 'ARMATURE': for bone in ob.data.bones: migrate_data(bone) + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = add_hubs_import_component( + component_name, blender_object) + + for property_name, property_value in component_value.items(): + if property_name == 'clip': + tracks = property_value.split(",") + for track_name in tracks: + if not has_track(blender_component.tracks_list, track_name): + track = blender_component.tracks_list.add() + track.name = track_name.strip() + + else: + assign_property(import_settings.vnodes, blender_component, + property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/video_texture_target.py b/addons/io_hubs_addon/components/definitions/video_texture_target.py index e1fba2fc..5d1051cd 100644 --- a/addons/io_hubs_addon/components/definitions/video_texture_target.py +++ b/addons/io_hubs_addon/components/definitions/video_texture_target.py @@ -3,7 +3,8 @@ from ..types import Category, PanelType, NodeType from ..utils import has_component from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property +from ...io.utils import gather_joint_property, gather_node_property, add_hubs_import_component + BLANK_ID = "pXph8WBzMu9fung" @@ -149,3 +150,16 @@ def gather(self, export_settings, object): 'srcNode': gather_joint_property(export_settings, self.srcNode, self, 'bone') if self.bone_id != BLANK_ID else gather_node_property( export_settings, object, self, 'srcNode'), } + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = add_hubs_import_component( + component_name, blender_object) + + for property_name, property_value in component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, + import_settings.vnodes[property_value['index']].blender_object) + + else: + setattr(blender_component, property_name, property_value) diff --git a/addons/io_hubs_addon/components/hubs_component.py b/addons/io_hubs_addon/components/hubs_component.py index 58b3fa76..8bf2621a 100644 --- a/addons/io_hubs_addon/components/hubs_component.py +++ b/addons/io_hubs_addon/components/hubs_component.py @@ -1,6 +1,7 @@ from bpy.types import PropertyGroup from ..io.utils import gather_properties from .types import Category, PanelType, NodeType +from ..io.utils import add_hubs_import_component, assign_property class HubsComponent(PropertyGroup): @@ -97,9 +98,16 @@ def pre_export(self, export_settings, object): '''This is called by the exporter before starting the export process''' pass - def gather(self, export_settings, object): + def gather(self, export_settings, blender_object): '''This is called by the exporter and will return all the component properties by default''' - return gather_properties(export_settings, object, self) + return gather_properties(export_settings, blender_object, self) + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + component = add_hubs_import_component(component_name, blender_object) + for property_name, property_value in component_value.items(): + assign_property(import_settings.vnodes, component, + property_name, property_value) def post_export(self, export_settings, object): '''This is called by the exporter after the export process has finished''' diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index 8bbc6564..ec358113 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -1,14 +1,8 @@ from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions from io_scene_gltf2.blender.exp import gltf2_blender_export import bpy -from bpy.props import PointerProperty, IntVectorProperty from ..components.components_registry import get_components_registry -from .utils import gather_lightmap_texture_info - -hubs_config = { - "gltfExtensionName": "MOZ_hubs_components", - "gltfExtensionVersion": 4, -} +from .utils import gather_lightmap_texture_info, HUBS_CONFIG def get_version_string(): @@ -74,11 +68,11 @@ def hubs_gather_gltf_hook(self, gltf2_object, export_settings): if not self.properties.enabled or not self.was_used: return - extension_name = hubs_config["gltfExtensionName"] + extension_name = HUBS_CONFIG["gltfExtensionName"] gltf2_object.extensions[extension_name] = self.Extension( name=extension_name, extension={ - "version": hubs_config["gltfExtensionVersion"], + "version": HUBS_CONFIG["gltfExtensionVersion"], "exporterVersion": get_version_string() }, required=False @@ -146,7 +140,7 @@ def add_hubs_components(self, gltf2_object, blender_object, export_settings): registered_hubs_components = get_components_registry() if component_list.items: - extension_name = hubs_config["gltfExtensionName"] + extension_name = HUBS_CONFIG["gltfExtensionName"] component_data = {} for component_item in component_list.items: @@ -172,78 +166,11 @@ def add_hubs_components(self, gltf2_object, blender_object, export_settings): self.was_used = True -class HubsComponentsExtensionProperties(bpy.types.PropertyGroup): - enabled: bpy.props.BoolProperty( - name="Export Hubs Components", - description='Include this extension in the exported glTF file.', - default=True - ) - version: IntVectorProperty(size=3) - - -class HubsGLTFExportPanel(bpy.types.Panel): - - bl_idname = "HBA_PT_Export_Panel" - bl_label = "Hubs Export Panel" - bl_space_type = 'FILE_BROWSER' - bl_region_type = 'TOOL_PROPS' - bl_label = "Hubs Components" - bl_parent_id = "GLTF_PT_export_user_extensions" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - sfile = context.space_data - operator = sfile.active_operator - return operator.bl_idname == "EXPORT_SCENE_OT_gltf" - - def draw_header(self, context): - props = bpy.context.scene.HubsComponentsExtensionProperties - self.layout.prop(props, 'enabled', text="") - - def draw(self, context): - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False # No animation. - - props = bpy.context.scene.HubsComponentsExtensionProperties - layout.active = props.enabled - - box = layout.box() - box.label(text="No options yet") - -# called by gltf-blender-io after it has loaded - - -def register_export_panel(): - try: - bpy.utils.register_class(HubsGLTFExportPanel) - except Exception: - pass - return unregister_export_panel - - -def unregister_export_panel(): - # Since panel is registered on demand, it is possible it is not registered - try: - bpy.utils.unregister_class(HubsGLTFExportPanel) - except Exception: - pass - - def register(): print("Register GLTF Exporter") - register_export_panel() gltf2_blender_export.__gather_gltf = patched_gather_gltf - bpy.utils.register_class(HubsComponentsExtensionProperties) - bpy.types.Scene.HubsComponentsExtensionProperties = PointerProperty( - type=HubsComponentsExtensionProperties) def unregister(): print("Unregister GLTF Exporter") - unregister_export_panel() - del bpy.types.Scene.HubsComponentsExtensionProperties - bpy.utils.unregister_class(HubsComponentsExtensionProperties) gltf2_blender_export.__gather_gltf = orig_gather_gltf - unregister_export_panel() diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 3388d74e..a8b924a7 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -1,342 +1,66 @@ +from io_scene_gltf2.io.com.gltf2_io_extensions import Extension import bpy -import traceback -import re -from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode -from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial -from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene -from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage +from .utils import HUBS_CONFIG -from ..components.utils import has_component, add_component -from ..components.definitions.loop_animation import has_track -# import hooks were only recently added to the glTF exporter, so make a custom hook for now -orig_BlenderNode_create_object = BlenderNode.create_object -orig_BlenderMaterial_create = BlenderMaterial.create -orig_BlenderScene_create = BlenderScene.create +class glTF2ImportUserExtension: -stored_components = {'object': {}, 'material': {}} + def __init__(self): + self.extensions = [ + Extension(name="MOZ_hubs_components", extension={}, required=True)] + self.properties = bpy.context.scene.hubs_import_properties -@staticmethod -def patched_BlenderNode_create_object(gltf, vnode_id): - obj = orig_BlenderNode_create_object(gltf, vnode_id) + def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import_settings): + if not self.properties.enabled: + return - vnode = gltf.vnodes[vnode_id] - node = None + self.add_hubs_components(gltf_scene, blender_scene, import_settings) - if vnode.camera_node_idx is not None: - parent_vnode = gltf.vnodes[vnode.parent] - if parent_vnode.name: - node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] + def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import_settings): + if not self.properties.enabled: + return - else: - if vnode.name: - node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + self.add_hubs_components( + gltf_node, blender_object, import_settings) + def gather_import_image_after_hook(self, gltf_img, blender_image, import_settings): + # As of Blender 3.2.0 the importer doesn't import images that are not referenced by a material socket. + # We handle this case by case in each component's gather_import override. + pass - if node is not None: - extensions = node.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['object'][node.name] = (vnode, node) + def gather_import_texture_after_hook(self, gltf_texture, node_tree, mh, tex_info, location, label, color_socket, alpha_socket, is_data, import_settings): + # As of Blender 3.2.0 the importer doesn't import textures that are not referenced by a material socket image. + # We handle this case by case in each component's gather_import override. + pass - return obj + def gather_import_material_after_hook(self, gltf_material, vertex_color, blender_mat, import_settings): + if not self.properties.enabled: + return -@staticmethod -def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): - orig_BlenderMaterial_create(gltf, material_idx, vertex_color) + self.add_hubs_components( + gltf_material, blender_mat, import_settings) - glb_material = gltf.data.materials[material_idx] + def add_hubs_components(self, gltf2_object, blender_object, import_settings): + extension_name = HUBS_CONFIG["gltfExtensionName"] + if not gltf2_object.extensions or extension_name not in gltf2_object.extensions: + return - if glb_material is not None: - extensions = glb_material.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['material'][glb_material.name] = glb_material - -@staticmethod -def patched_BlenderScene_create(gltf): - global stored_components - orig_BlenderScene_create(gltf) - - create_object_hubs_components(gltf) - create_material_hubs_components(gltf) - create_scene_hubs_components(gltf) - - # clear stored components so as not to conflict with the next import - for key in stored_components.keys(): - stored_components[key].clear() - - -def create_object_hubs_components(gltf): - special_cases = { - 'networked': handle_networked, - #'audio-target': handle_audio_target, - 'spawn-point': handle_spawn_point, - 'heightfield': handle_heightfield, - 'box-collider': handle_box_collider, - 'scene-preview-camera': handle_scene_preview_camera, - 'trimesh': handle_trimesh, - 'spawner': handle_spawner, - 'loop-animation': handle_loop_animation, - } - - for vnode, node in stored_components['object'].values(): - MOZ_hubs_components = node.extensions['MOZ_hubs_components'] - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name](gltf, vnode, node, glb_component_name, glb_component_value) - continue - - else: - blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf, blender_component, property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - -def create_material_hubs_components(gltf): - special_cases = { - #'video-texture-target': handle_video_texture_target, - } - - for glb_material in stored_components['material'].values(): - MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] - - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name](gltf, glb_material, glb_component_name, glb_component_value) - continue - - else: - blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf, blender_component, property_name, property_value) - - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - -def create_scene_hubs_components(gltf): - if gltf.data.scene is None: - return - - special_cases = { - 'environment-settings': handle_environment_settings, - 'background': handle_background, - } - - gltf_scene = gltf.data.scenes[gltf.data.scene] - extensions = gltf_scene.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name](gltf, glb_component_name, glb_component_value) - continue - - blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf, blender_component, property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - - -# OBJECT SPECIAL CASES -def handle_networked(gltf, vnode, node, glb_component_name, glb_component_value): - return - -def handle_audio_target(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - -def handle_spawn_point(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", "waypoint", glb_component_value, vnode=vnode, node=node) - - blender_component.canBeSpawnPoint = True - -def handle_heightfield(gltf, vnode, node, glb_component_name, glb_component_value): - return - -def handle_box_collider(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", "ammo-shape", glb_component_value, vnode=vnode, node=node) - - blender_component.type = "box" - -def handle_scene_preview_camera(gltf, vnode, node, glb_component_name, glb_component_value): - return - -def handle_trimesh(gltf, vnode, node, glb_component_name, glb_component_value): - return - -def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'mediaOptions': - setattr(blender_component, "applyGravity", property_value["applyGravity"]) - - else: - assign_property(gltf, blender_component, property_name, property_value) - -def handle_loop_animation(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component("object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'clip': - tracks = property_value.split(",") - for track_name in tracks: - if not has_track(blender_component.tracks_list, track_name): - track = blender_component.tracks_list.add() - track.name = track_name.strip() - - else: - assign_property(gltf, blender_component, property_name, property_value) - - -# MATERIAL SPECIAL CASES -def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): - blender_component = add_hubs_component("material", glb_component_name, glb_component_value, glb_material=glb_material) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - -# SCENE SPECIAL CASES -def handle_environment_settings(gltf, glb_component_name, glb_component_value): - blender_component = add_hubs_component("scene", glb_component_name, glb_component_value, gltf=gltf) - - # load environment maps - enviro_imgs = {} - for gltf_texture in gltf.data.textures: - extensions = gltf_texture.extensions - if extensions: - MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') - if MOZ_texture_rgbe: - BlenderImage.create(gltf, MOZ_texture_rgbe['source']) - pyimg = gltf.data.images[MOZ_texture_rgbe['source']] - blender_image_name = pyimg.blender_image_name - enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name - - - for property_name, property_value in glb_component_value.items(): - if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": - blender_image_name = enviro_imgs[property_value['index']] - blender_image = bpy.data.images[blender_image_name] - - setattr(blender_component, property_name, blender_image) - - else: - assign_property(gltf, blender_component, property_name, property_value) - -def handle_background(gltf, glb_component_name, glb_component_value): - blender_component = add_hubs_component("scene", "environment-settings", glb_component_value, gltf=gltf) - - blender_component.toneMapping = "LinearToneMapping" - - set_color_from_hex(blender_component, "backgroundColor", glb_component_value['color']) - - -# UTILITIES -def add_hubs_component(element_type, glb_component_name, glb_component_value, vnode=None, node=None, glb_material=None, gltf=None): - # get element - if element_type == "object": - element = vnode.blender_object - - elif element_type == "material": - element = bpy.data.materials[glb_material.blender_material[None]] - - elif element_type == "scene": - element = bpy.data.scenes[gltf.blender_scene] - - else: - element = None - - # print debug info - if element_type == "object": - print(f"Node Name: {node.name}") - print(f"Object: {element}") - - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - - # create component - if not has_component(element, glb_component_name): - add_component(element, glb_component_name) - - return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") - -def set_color_from_hex(blender_component, property_name, hexcolor): - hexcolor = hexcolor.lstrip('#') - rgb_int = [int(hexcolor[i:i+2], 16) for i in (0, 2, 4)] - - for x, value in enumerate(rgb_int): - rgb_float = value/255 if value > 0 else 0 - - # convert sRGB values to linear - if rgb_float < 0.04045: - rgb_float_linear = rgb_float * (1.0 / 12.92) - - else: - rgb_float_linear = ((rgb_float + 0.055) * (1.0 / 1.055)) ** 2.4 - - print(f"{property_name}[{x}] = {rgb_float_linear}") - getattr(blender_component, property_name)[x] = rgb_float_linear - -def assign_property(gltf, blender_component, property_name, property_value): - if isinstance(property_value, dict): - if property_value.get('__mhc_link_type'): - if len(property_value) == 2: - setattr(blender_component, property_name, gltf.vnodes[property_value['index']].blender_object) - - else: - blender_subcomponent = getattr(blender_component, property_name) - for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") - blender_subcomponent[x] = subproperty_value - - elif re.fullmatch("#[0-9a-fA-F]*", str(property_value)): - set_color_from_hex(blender_component, property_name, property_value) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) + components_data = gltf2_object.extensions[extension_name] + from ..components.components_registry import get_component_by_name + for component_name in components_data.keys(): + component_class = get_component_by_name(component_name) + if component_class: + component_value = components_data[component_name] + component_class.gather_import( + import_settings, blender_object, component_name, component_value) + else: + print('Could not import unsupported component "%s"' % + (component_name)) def register(): - BlenderNode.create_object = patched_BlenderNode_create_object - BlenderMaterial.create = patched_BlenderMaterial_create - BlenderScene.create = patched_BlenderScene_create + print("Register GLTF Exporter") + def unregister(): - BlenderNode.create_object = orig_BlenderNode_create_object - BlenderMaterial.create = orig_BlenderMaterial_create - BlenderScene.create = orig_BlenderScene_create + print("Unregister GLTF Exporter") diff --git a/addons/io_hubs_addon/io/gltf_importer_compat.py b/addons/io_hubs_addon/io/gltf_importer_compat.py new file mode 100644 index 00000000..66490763 --- /dev/null +++ b/addons/io_hubs_addon/io/gltf_importer_compat.py @@ -0,0 +1,313 @@ +import bpy +import traceback +from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode +from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial +from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene +from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage + +from ..components.definitions.loop_animation import has_track +from .utils import add_hubs_component, assign_property, set_color_from_hex + +# import hooks were only recently added to the glTF exporter, so make a custom hook for now +orig_BlenderNode_create_object = BlenderNode.create_object +orig_BlenderMaterial_create = BlenderMaterial.create +orig_BlenderScene_create = BlenderScene.create + +stored_components = {'object': {}, 'material': {}} + + +@staticmethod +def patched_BlenderNode_create_object(gltf, vnode_id): + obj = orig_BlenderNode_create_object(gltf, vnode_id) + + vnode = gltf.vnodes[vnode_id] + node = None + + if vnode.camera_node_idx is not None: + parent_vnode = gltf.vnodes[vnode.parent] + if parent_vnode.name: + node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] + + else: + if vnode.name: + node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + + if node is not None: + extensions = node.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['object'][node.name] = (vnode, node) + + return obj + + +@staticmethod +def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): + orig_BlenderMaterial_create(gltf, material_idx, vertex_color) + + glb_material = gltf.data.materials[material_idx] + + if glb_material is not None: + extensions = glb_material.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + stored_components['material'][glb_material.name] = glb_material + + +@staticmethod +def patched_BlenderScene_create(gltf): + global stored_components + orig_BlenderScene_create(gltf) + + create_object_hubs_components(gltf) + create_material_hubs_components(gltf) + create_scene_hubs_components(gltf) + + # clear stored components so as not to conflict with the next import + for key in stored_components.keys(): + stored_components[key].clear() + + +def create_object_hubs_components(gltf): + special_cases = { + 'networked': handle_networked, + # 'audio-target': handle_audio_target, + 'spawn-point': handle_spawn_point, + 'heightfield': handle_heightfield, + 'box-collider': handle_box_collider, + 'scene-preview-camera': handle_scene_preview_camera, + 'trimesh': handle_trimesh, + 'spawner': handle_spawner, + 'loop-animation': handle_loop_animation, + } + + for vnode, node in stored_components['object'].values(): + MOZ_hubs_components = node.extensions['MOZ_hubs_components'] + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name]( + gltf, vnode, node, glb_component_name, glb_component_value) + continue + + else: + blender_component = add_hubs_component( + "object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + + +def create_material_hubs_components(gltf): + special_cases = { + # 'video-texture-target': handle_video_texture_target, + } + + for glb_material in stored_components['material'].values(): + MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] + + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name]( + gltf, glb_material, glb_component_name, glb_component_value) + continue + + else: + blender_component = add_hubs_component( + "material", glb_component_name, glb_component_value, glb_material=glb_material) + + for property_name, property_value in glb_component_value.items(): + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + + +def create_scene_hubs_components(gltf): + if gltf.data.scene is None: + return + + special_cases = { + 'environment-settings': handle_environment_settings, + 'background': handle_background, + } + + gltf_scene = gltf.data.scenes[gltf.data.scene] + extensions = gltf_scene.extensions + if extensions: + MOZ_hubs_components = extensions.get('MOZ_hubs_components') + if MOZ_hubs_components: + for glb_component_name, glb_component_value in MOZ_hubs_components.items(): + try: + if glb_component_name in special_cases.keys(): + special_cases[glb_component_name]( + gltf, glb_component_name, glb_component_value) + continue + + blender_component = add_hubs_component( + "scene", glb_component_name, glb_component_value, gltf=gltf) + + for property_name, property_value in glb_component_value.items(): + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + except Exception: + print("Error encountered while adding Hubs components:") + traceback.print_exc() + print("Continuing on....\n") + + +# OBJECT SPECIAL CASES +def handle_networked(gltf, vnode, node, glb_component_name, glb_component_value): + return + + +def handle_audio_target(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, + gltf.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + +def handle_spawn_point(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "object", "waypoint", glb_component_value, vnode=vnode, node=node) + + blender_component.canBeSpawnPoint = True + + +def handle_heightfield(gltf, vnode, node, glb_component_name, glb_component_value): + return + + +def handle_box_collider(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "object", "ammo-shape", glb_component_value, vnode=vnode, node=node) + + blender_component.type = "box" + + +def handle_scene_preview_camera(gltf, vnode, node, glb_component_name, glb_component_value): + return + + +def handle_trimesh(gltf, vnode, node, glb_component_name, glb_component_value): + return + + +def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'mediaOptions': + setattr(blender_component, "applyGravity", + property_value["applyGravity"]) + + else: + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + +def handle_loop_animation(gltf, vnode, node, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "object", glb_component_name, glb_component_value, vnode=vnode, node=node) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'clip': + tracks = property_value.split(",") + for track_name in tracks: + if not has_track(blender_component.tracks_list, track_name): + track = blender_component.tracks_list.add() + track.name = track_name.strip() + + else: + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + +# MATERIAL SPECIAL CASES +def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "material", glb_component_name, glb_component_value, glb_material=glb_material) + + for property_name, property_value in glb_component_value.items(): + if property_name == 'srcNode': + setattr(blender_component, property_name, + gltf.vnodes[property_value['index']].blender_object) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) + + +# SCENE SPECIAL CASES +def handle_environment_settings(gltf, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "scene", glb_component_name, glb_component_value, gltf=gltf) + + # load environment maps + enviro_imgs = {} + for gltf_texture in gltf.data.textures: + extensions = gltf_texture.extensions + if extensions: + MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') + if MOZ_texture_rgbe: + BlenderImage.create(gltf, MOZ_texture_rgbe['source']) + pyimg = gltf.data.images[MOZ_texture_rgbe['source']] + blender_image_name = pyimg.blender_image_name + enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name + + for property_name, property_value in glb_component_value.items(): + if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": + blender_image_name = enviro_imgs[property_value['index']] + blender_image = bpy.data.images[blender_image_name] + + setattr(blender_component, property_name, blender_image) + + else: + assign_property(gltf.vnodes, blender_component, + property_name, property_value) + + +def handle_background(gltf, glb_component_name, glb_component_value): + blender_component = add_hubs_component( + "scene", "environment-settings", glb_component_value, gltf=gltf) + + blender_component.toneMapping = "LinearToneMapping" + + set_color_from_hex(blender_component, "backgroundColor", + glb_component_value['color']) + + +def register(): + print("Register GLTF Importer") + BlenderNode.create_object = patched_BlenderNode_create_object + BlenderMaterial.create = patched_BlenderMaterial_create + BlenderScene.create = patched_BlenderScene_create + + +def unregister(): + print("Unregister GLTF Importer") + BlenderNode.create_object = orig_BlenderNode_create_object + BlenderMaterial.create = orig_BlenderMaterial_create + BlenderScene.create = orig_BlenderScene_create diff --git a/addons/io_hubs_addon/io/panels.py b/addons/io_hubs_addon/io/panels.py new file mode 100644 index 00000000..0098d1db --- /dev/null +++ b/addons/io_hubs_addon/io/panels.py @@ -0,0 +1,121 @@ +import bpy +from bpy.props import PointerProperty, IntVectorProperty, BoolProperty + + +class HubsComponentsExtensionProperties(bpy.types.PropertyGroup): + enabled: bpy.props.BoolProperty( + name="Export Hubs Components", + description='Include this extension in the exported glTF file', + default=True + ) + version: IntVectorProperty(size=3) + + +class HubsGLTFExportPanel(bpy.types.Panel): + + bl_idname = "HBA_PT_Export_Panel" + bl_label = "Hubs Export Panel" + bl_space_type = 'FILE_BROWSER' + bl_region_type = 'TOOL_PROPS' + bl_label = "Hubs Components" + bl_parent_id = "GLTF_PT_export_user_extensions" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + sfile = context.space_data + operator = sfile.active_operator + return operator.bl_idname == "EXPORT_SCENE_OT_gltf" + + def draw_header(self, context): + props = bpy.context.scene.HubsComponentsExtensionProperties + self.layout.prop(props, 'enabled', text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + props = bpy.context.scene.HubsComponentsExtensionProperties + layout.active = props.enabled + + box = layout.box() + box.label(text="No options yet") + + +class HubsGLTFImportPanel(bpy.types.Panel): + + bl_idname = "HBA_PT_Import_Panel" + bl_label = "Hubs Import Panel" + bl_space_type = 'FILE_BROWSER' + bl_region_type = 'TOOL_PROPS' + bl_label = "Hubs Components" + bl_parent_id = "GLTF_PT_import_user_extensions" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + sfile = context.space_data + operator = sfile.active_operator + return operator.bl_idname == "IMPORT_SCENE_OT_gltf" + + def draw_header(self, context): + props = bpy.context.scene.hubs_import_properties + self.layout.prop(props, 'enabled', text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + props = bpy.context.scene.hubs_import_properties + layout.active = props.enabled + + box = layout.box() + box.label(text="No options yet") + + +class HubsImportProperties(bpy.types.PropertyGroup): + enabled: BoolProperty( + name="Import Hubs Components", + description='Import Hubs components from the glTF file', + default=True + ) + +# called by gltf-blender-io after it has loaded + + +def register_panels(): + try: + bpy.utils.register_class(HubsGLTFExportPanel) + bpy.utils.register_class(HubsGLTFImportPanel) + except Exception: + pass + return unregister_panels + + +def unregister_panels(): + # Since panel is registered on demand, it is possible it is not registered + try: + bpy.utils.unregister_class(HubsGLTFImportPanel) + bpy.utils.unregister_class(HubsGLTFExportPanel) + except Exception: + pass + + +def register(): + register_panels() + bpy.utils.register_class(HubsComponentsExtensionProperties) + bpy.types.Scene.HubsComponentsExtensionProperties = PointerProperty( + type=HubsComponentsExtensionProperties) + bpy.utils.register_class(HubsImportProperties) + bpy.types.Scene.hubs_import_properties = PointerProperty( + type=HubsImportProperties) + + +def unregister(): + del bpy.types.Scene.HubsComponentsExtensionProperties + bpy.utils.unregister_class(HubsComponentsExtensionProperties) + del bpy.types.Scene.hubs_import_properties + bpy.utils.unregister_class(HubsImportProperties) + unregister_panels() diff --git a/addons/io_hubs_addon/io/utils.py b/addons/io_hubs_addon/io/utils.py index 83712e6c..9eb46432 100644 --- a/addons/io_hubs_addon/io/utils.py +++ b/addons/io_hubs_addon/io/utils.py @@ -13,6 +13,12 @@ from io_scene_gltf2.blender.exp import gltf2_blender_export_keys from typing import Optional from ..nodes.lightmap import MozLightmapNode +import re + +HUBS_CONFIG = { + "gltfExtensionName": "MOZ_hubs_components", + "gltfExtensionVersion": 4, +} # gather_texture/image with HDR support via MOZ_texture_rgbe @@ -340,3 +346,83 @@ def gather_lightmap_texture_info(blender_material, export_settings): "index": texture_info.index, "texCoord": texture_info.tex_coord } + + +def add_hubs_import_component(component_name, blender_object): + from ..components.utils import add_component, has_component + from ..components.components_registry import get_component_by_name + component_class = get_component_by_name(component_name) + if component_class: + if not has_component(blender_object, component_name): + add_component(blender_object, component_name) + + return getattr(blender_object, component_class.get_id()) + + +def add_hubs_component(element_type, glb_component_name, glb_component_value, vnode=None, node=None, glb_material=None, gltf=None): + # get element + if element_type == "object": + element = vnode.blender_object + + elif element_type == "material": + element = bpy.data.materials[glb_material.blender_material[None]] + + elif element_type == "scene": + element = bpy.data.scenes[gltf.blender_scene] + + else: + element = None + + # print debug info + if element_type == "object": + print(f"Node Name: {node.name}") + print(f"Object: {element}") + + print(f"Hubs Component Name: {glb_component_name}") + print(f"Hubs Component Value: {glb_component_value}") + + # create component + from ..components.utils import add_component, has_component + if not has_component(element, glb_component_name): + add_component(element, glb_component_name) + + return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") + + +def set_color_from_hex(blender_component, property_name, hexcolor): + hexcolor = hexcolor.lstrip('#') + rgb_int = [int(hexcolor[i:i+2], 16) for i in (0, 2, 4)] + + for x, value in enumerate(rgb_int): + rgb_float = value/255 if value > 0 else 0 + + # convert sRGB values to linear + if rgb_float < 0.04045: + rgb_float_linear = rgb_float * (1.0 / 12.92) + + else: + rgb_float_linear = ((rgb_float + 0.055) * (1.0 / 1.055)) ** 2.4 + + print(f"{property_name}[{x}] = {rgb_float_linear}") + getattr(blender_component, property_name)[x] = rgb_float_linear + + +def assign_property(vnodes, blender_component, property_name, property_value): + if isinstance(property_value, dict): + if property_value.get('__mhc_link_type'): + if len(property_value) == 2: + setattr(blender_component, property_name, + vnodes[property_value['index']].blender_object) + + else: + blender_subcomponent = getattr(blender_component, property_name) + for x, subproperty_value in enumerate(property_value.values()): + print(f"{property_name}[{x}] = {subproperty_value}") + blender_subcomponent[x] = subproperty_value + + elif re.fullmatch("#[0-9a-fA-F]*", str(property_value)): + set_color_from_hex(blender_component, property_name, property_value) + + else: + print(f"{property_name} = {property_value}") + setattr(blender_component, property_name, property_value) From 7141691baa155d59a8e59d0639bf0d021e647db2 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 28 Jul 2022 14:21:12 +0200 Subject: [PATCH 15/43] Simplify compat import --- .../components/definitions/audio_target.py | 4 +- .../components/definitions/background.py | 4 +- .../definitions/environment_settings.py | 4 +- .../components/definitions/loop_animation.py | 4 +- .../definitions/video_texture_target.py | 4 +- .../components/hubs_component.py | 4 +- addons/io_hubs_addon/io/gltf_importer.py | 2 +- .../io_hubs_addon/io/gltf_importer_compat.py | 290 ++---------------- addons/io_hubs_addon/io/utils.py | 35 +-- 9 files changed, 43 insertions(+), 308 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/audio_target.py b/addons/io_hubs_addon/components/definitions/audio_target.py index 75a4c7c9..da4ae5c9 100644 --- a/addons/io_hubs_addon/components/definitions/audio_target.py +++ b/addons/io_hubs_addon/components/definitions/audio_target.py @@ -4,7 +4,7 @@ from ..utils import has_component from ..types import Category, PanelType, NodeType from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property, add_hubs_import_component +from ...io.utils import gather_joint_property, gather_node_property, import_component BLANK_ID = "374e54CMHFCipSk" @@ -162,7 +162,7 @@ def gather(self, export_settings, object): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = add_hubs_import_component( + blender_component = import_component( component_name, blender_object) for property_name, property_value in component_value.items(): diff --git a/addons/io_hubs_addon/components/definitions/background.py b/addons/io_hubs_addon/components/definitions/background.py index 00402fcf..10a0cb8d 100644 --- a/addons/io_hubs_addon/components/definitions/background.py +++ b/addons/io_hubs_addon/components/definitions/background.py @@ -1,4 +1,4 @@ -from ...io.utils import add_hubs_import_component, assign_property +from ...io.utils import import_component, assign_property from ..hubs_component import HubsComponent from ..types import NodeType @@ -12,7 +12,7 @@ class EnvironmentSettings(HubsComponent): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = add_hubs_import_component( + blender_component = import_component( 'environemnt-settings', blender_object) for property_name, property_value in component_value.items(): assign_property(import_settings.vnodes, blender_component, diff --git a/addons/io_hubs_addon/components/definitions/environment_settings.py b/addons/io_hubs_addon/components/definitions/environment_settings.py index 2f0355aa..e93cba40 100644 --- a/addons/io_hubs_addon/components/definitions/environment_settings.py +++ b/addons/io_hubs_addon/components/definitions/environment_settings.py @@ -1,6 +1,6 @@ from bpy.props import FloatProperty, EnumProperty, FloatVectorProperty, PointerProperty from bpy.types import Image -from ...io.utils import add_hubs_import_component, assign_property, gather_texture_property, gather_color_property +from ...io.utils import import_component, assign_property, gather_texture_property, gather_color_property from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType import bpy @@ -75,7 +75,7 @@ def gather(self, export_settings, object): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = add_hubs_import_component( + blender_component = import_component( component_name, blender_object) images = {} diff --git a/addons/io_hubs_addon/components/definitions/loop_animation.py b/addons/io_hubs_addon/components/definitions/loop_animation.py index 27037805..b9522c6c 100644 --- a/addons/io_hubs_addon/components/definitions/loop_animation.py +++ b/addons/io_hubs_addon/components/definitions/loop_animation.py @@ -4,7 +4,7 @@ from bpy.types import PropertyGroup, Menu, Operator from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType -from ...io.utils import add_hubs_import_component, assign_property +from ...io.utils import import_component, assign_property class TracksList(bpy.types.UIList): @@ -202,7 +202,7 @@ def migrate_data(ob): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = add_hubs_import_component( + blender_component = import_component( component_name, blender_object) for property_name, property_value in component_value.items(): diff --git a/addons/io_hubs_addon/components/definitions/video_texture_target.py b/addons/io_hubs_addon/components/definitions/video_texture_target.py index 5d1051cd..d0aafb99 100644 --- a/addons/io_hubs_addon/components/definitions/video_texture_target.py +++ b/addons/io_hubs_addon/components/definitions/video_texture_target.py @@ -3,7 +3,7 @@ from ..types import Category, PanelType, NodeType from ..utils import has_component from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property, add_hubs_import_component +from ...io.utils import gather_joint_property, gather_node_property, import_component BLANK_ID = "pXph8WBzMu9fung" @@ -153,7 +153,7 @@ def gather(self, export_settings, object): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = add_hubs_import_component( + blender_component = import_component( component_name, blender_object) for property_name, property_value in component_value.items(): diff --git a/addons/io_hubs_addon/components/hubs_component.py b/addons/io_hubs_addon/components/hubs_component.py index 8bf2621a..8d03b840 100644 --- a/addons/io_hubs_addon/components/hubs_component.py +++ b/addons/io_hubs_addon/components/hubs_component.py @@ -1,7 +1,7 @@ from bpy.types import PropertyGroup from ..io.utils import gather_properties from .types import Category, PanelType, NodeType -from ..io.utils import add_hubs_import_component, assign_property +from ..io.utils import import_component, assign_property class HubsComponent(PropertyGroup): @@ -104,7 +104,7 @@ def gather(self, export_settings, blender_object): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): - component = add_hubs_import_component(component_name, blender_object) + component = import_component(component_name, blender_object) for property_name, property_value in component_value.items(): assign_property(import_settings.vnodes, component, property_name, property_value) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index a8b924a7..9342a55e 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -1,5 +1,5 @@ -from io_scene_gltf2.io.com.gltf2_io_extensions import Extension import bpy +from io_scene_gltf2.io.com.gltf2_io_extensions import Extension from .utils import HUBS_CONFIG diff --git a/addons/io_hubs_addon/io/gltf_importer_compat.py b/addons/io_hubs_addon/io/gltf_importer_compat.py index 66490763..05a42de2 100644 --- a/addons/io_hubs_addon/io/gltf_importer_compat.py +++ b/addons/io_hubs_addon/io/gltf_importer_compat.py @@ -1,24 +1,37 @@ import bpy -import traceback from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene -from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage - -from ..components.definitions.loop_animation import has_track -from .utils import add_hubs_component, assign_property, set_color_from_hex +from .utils import HUBS_CONFIG # import hooks were only recently added to the glTF exporter, so make a custom hook for now orig_BlenderNode_create_object = BlenderNode.create_object orig_BlenderMaterial_create = BlenderMaterial.create orig_BlenderScene_create = BlenderScene.create -stored_components = {'object': {}, 'material': {}} +EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] + + +def add_hubs_components(gltf2_object, blender_object, import_settings): + if not gltf2_object.extensions or EXTENSION_NAME not in gltf2_object.extensions: + return + + components_data = gltf2_object.extensions[EXTENSION_NAME] + from ..components.components_registry import get_component_by_name + for component_name in components_data.keys(): + component_class = get_component_by_name(component_name) + if component_class: + component_value = components_data[component_name] + component_class.gather_import( + import_settings, blender_object, component_name, component_value) + else: + print('Could not import unsupported component "%s"' % + (component_name)) @staticmethod def patched_BlenderNode_create_object(gltf, vnode_id): - obj = orig_BlenderNode_create_object(gltf, vnode_id) + blender_object = orig_BlenderNode_create_object(gltf, vnode_id) vnode = gltf.vnodes[vnode_id] node = None @@ -32,271 +45,26 @@ def patched_BlenderNode_create_object(gltf, vnode_id): if vnode.name: node = [n for n in gltf.data.nodes if n.name == vnode.name][0] - if node is not None: - extensions = node.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['object'][node.name] = (vnode, node) + add_hubs_components(node, vnode.blender_object, gltf) - return obj + return blender_object @staticmethod def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): - orig_BlenderMaterial_create(gltf, material_idx, vertex_color) - - glb_material = gltf.data.materials[material_idx] - - if glb_material is not None: - extensions = glb_material.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - stored_components['material'][glb_material.name] = glb_material + orig_BlenderMaterial_create( + gltf, material_idx, vertex_color) + gltf_material = gltf.data.materials[material_idx] + blender_object = bpy.data.materials[gltf_material.blender_material[None]] + add_hubs_components(gltf_material, blender_object, gltf) @staticmethod def patched_BlenderScene_create(gltf): - global stored_components orig_BlenderScene_create(gltf) - - create_object_hubs_components(gltf) - create_material_hubs_components(gltf) - create_scene_hubs_components(gltf) - - # clear stored components so as not to conflict with the next import - for key in stored_components.keys(): - stored_components[key].clear() - - -def create_object_hubs_components(gltf): - special_cases = { - 'networked': handle_networked, - # 'audio-target': handle_audio_target, - 'spawn-point': handle_spawn_point, - 'heightfield': handle_heightfield, - 'box-collider': handle_box_collider, - 'scene-preview-camera': handle_scene_preview_camera, - 'trimesh': handle_trimesh, - 'spawner': handle_spawner, - 'loop-animation': handle_loop_animation, - } - - for vnode, node in stored_components['object'].values(): - MOZ_hubs_components = node.extensions['MOZ_hubs_components'] - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name]( - gltf, vnode, node, glb_component_name, glb_component_value) - continue - - else: - blender_component = add_hubs_component( - "object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - - -def create_material_hubs_components(gltf): - special_cases = { - # 'video-texture-target': handle_video_texture_target, - } - - for glb_material in stored_components['material'].values(): - MOZ_hubs_components = glb_material.extensions['MOZ_hubs_components'] - - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name]( - gltf, glb_material, glb_component_name, glb_component_value) - continue - - else: - blender_component = add_hubs_component( - "material", glb_component_name, glb_component_value, glb_material=glb_material) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - - -def create_scene_hubs_components(gltf): - if gltf.data.scene is None: - return - - special_cases = { - 'environment-settings': handle_environment_settings, - 'background': handle_background, - } - gltf_scene = gltf.data.scenes[gltf.data.scene] - extensions = gltf_scene.extensions - if extensions: - MOZ_hubs_components = extensions.get('MOZ_hubs_components') - if MOZ_hubs_components: - for glb_component_name, glb_component_value in MOZ_hubs_components.items(): - try: - if glb_component_name in special_cases.keys(): - special_cases[glb_component_name]( - gltf, glb_component_name, glb_component_value) - continue - - blender_component = add_hubs_component( - "scene", glb_component_name, glb_component_value, gltf=gltf) - - for property_name, property_value in glb_component_value.items(): - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - except Exception: - print("Error encountered while adding Hubs components:") - traceback.print_exc() - print("Continuing on....\n") - - -# OBJECT SPECIAL CASES -def handle_networked(gltf, vnode, node, glb_component_name, glb_component_value): - return - - -def handle_audio_target(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, - gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - -def handle_spawn_point(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "object", "waypoint", glb_component_value, vnode=vnode, node=node) - - blender_component.canBeSpawnPoint = True - - -def handle_heightfield(gltf, vnode, node, glb_component_name, glb_component_value): - return - - -def handle_box_collider(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "object", "ammo-shape", glb_component_value, vnode=vnode, node=node) - - blender_component.type = "box" - - -def handle_scene_preview_camera(gltf, vnode, node, glb_component_name, glb_component_value): - return - - -def handle_trimesh(gltf, vnode, node, glb_component_name, glb_component_value): - return - - -def handle_spawner(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'mediaOptions': - setattr(blender_component, "applyGravity", - property_value["applyGravity"]) - - else: - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - -def handle_loop_animation(gltf, vnode, node, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "object", glb_component_name, glb_component_value, vnode=vnode, node=node) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'clip': - tracks = property_value.split(",") - for track_name in tracks: - if not has_track(blender_component.tracks_list, track_name): - track = blender_component.tracks_list.add() - track.name = track_name.strip() - - else: - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - -# MATERIAL SPECIAL CASES -def handle_video_texture_target(gltf, glb_material, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "material", glb_component_name, glb_component_value, glb_material=glb_material) - - for property_name, property_value in glb_component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, - gltf.vnodes[property_value['index']].blender_object) - - else: - print(f"{property_name} = {property_value}") - setattr(blender_component, property_name, property_value) - - -# SCENE SPECIAL CASES -def handle_environment_settings(gltf, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "scene", glb_component_name, glb_component_value, gltf=gltf) - - # load environment maps - enviro_imgs = {} - for gltf_texture in gltf.data.textures: - extensions = gltf_texture.extensions - if extensions: - MOZ_texture_rgbe = extensions.get('MOZ_texture_rgbe') - if MOZ_texture_rgbe: - BlenderImage.create(gltf, MOZ_texture_rgbe['source']) - pyimg = gltf.data.images[MOZ_texture_rgbe['source']] - blender_image_name = pyimg.blender_image_name - enviro_imgs[MOZ_texture_rgbe['source']] = blender_image_name - - for property_name, property_value in glb_component_value.items(): - if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": - blender_image_name = enviro_imgs[property_value['index']] - blender_image = bpy.data.images[blender_image_name] - - setattr(blender_component, property_name, blender_image) - - else: - assign_property(gltf.vnodes, blender_component, - property_name, property_value) - - -def handle_background(gltf, glb_component_name, glb_component_value): - blender_component = add_hubs_component( - "scene", "environment-settings", glb_component_value, gltf=gltf) - - blender_component.toneMapping = "LinearToneMapping" - - set_color_from_hex(blender_component, "backgroundColor", - glb_component_value['color']) + blender_object = bpy.data.scenes[gltf.blender_scene] + add_hubs_components(gltf_scene, blender_object, gltf) def register(): diff --git a/addons/io_hubs_addon/io/utils.py b/addons/io_hubs_addon/io/utils.py index 9eb46432..43db9ebc 100644 --- a/addons/io_hubs_addon/io/utils.py +++ b/addons/io_hubs_addon/io/utils.py @@ -348,7 +348,7 @@ def gather_lightmap_texture_info(blender_material, export_settings): } -def add_hubs_import_component(component_name, blender_object): +def import_component(component_name, blender_object): from ..components.utils import add_component, has_component from ..components.components_registry import get_component_by_name component_class = get_component_by_name(component_name) @@ -359,36 +359,6 @@ def add_hubs_import_component(component_name, blender_object): return getattr(blender_object, component_class.get_id()) -def add_hubs_component(element_type, glb_component_name, glb_component_value, vnode=None, node=None, glb_material=None, gltf=None): - # get element - if element_type == "object": - element = vnode.blender_object - - elif element_type == "material": - element = bpy.data.materials[glb_material.blender_material[None]] - - elif element_type == "scene": - element = bpy.data.scenes[gltf.blender_scene] - - else: - element = None - - # print debug info - if element_type == "object": - print(f"Node Name: {node.name}") - print(f"Object: {element}") - - print(f"Hubs Component Name: {glb_component_name}") - print(f"Hubs Component Value: {glb_component_value}") - - # create component - from ..components.utils import add_component, has_component - if not has_component(element, glb_component_name): - add_component(element, glb_component_name) - - return getattr(element, f"hubs_component_{glb_component_name.replace('-', '_')}") - - def set_color_from_hex(blender_component, property_name, hexcolor): hexcolor = hexcolor.lstrip('#') rgb_int = [int(hexcolor[i:i+2], 16) for i in (0, 2, 4)] @@ -403,7 +373,6 @@ def set_color_from_hex(blender_component, property_name, hexcolor): else: rgb_float_linear = ((rgb_float + 0.055) * (1.0 / 1.055)) ** 2.4 - print(f"{property_name}[{x}] = {rgb_float_linear}") getattr(blender_component, property_name)[x] = rgb_float_linear @@ -417,12 +386,10 @@ def assign_property(vnodes, blender_component, property_name, property_value): else: blender_subcomponent = getattr(blender_component, property_name) for x, subproperty_value in enumerate(property_value.values()): - print(f"{property_name}[{x}] = {subproperty_value}") blender_subcomponent[x] = subproperty_value elif re.fullmatch("#[0-9a-fA-F]*", str(property_value)): set_color_from_hex(blender_component, property_name, property_value) else: - print(f"{property_name} = {property_value}") setattr(blender_component, property_name, property_value) From 1dc2129d67453c4712a573fa13ace7f0b72bc695 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 28 Jul 2022 14:34:24 +0200 Subject: [PATCH 16/43] Consolidate into one GLTF importer --- addons/io_hubs_addon/__init__.py | 8 +- .../components/definitions/visible.py | 3 +- addons/io_hubs_addon/io/gltf_exporter.py | 10 ++- addons/io_hubs_addon/io/gltf_importer.py | 90 +++++++++++++++---- .../io_hubs_addon/io/gltf_importer_compat.py | 81 ----------------- 5 files changed, 85 insertions(+), 107 deletions(-) delete mode 100644 addons/io_hubs_addon/io/gltf_importer_compat.py diff --git a/addons/io_hubs_addon/__init__.py b/addons/io_hubs_addon/__init__.py index 8471fed7..6171c9c3 100644 --- a/addons/io_hubs_addon/__init__.py +++ b/addons/io_hubs_addon/__init__.py @@ -1,10 +1,6 @@ from . import (nodes, components) -from .io import gltf_exporter, panels +from .io import gltf_exporter, gltf_importer, panels import bpy -if bpy.app.version < (3, 0, 0): - from .io import gltf_importer_compat as gltf_importer -else: - from .io import gltf_importer bl_info = { "name": "Hubs Blender Addon", @@ -39,11 +35,9 @@ def unregister(): # called by gltf-blender-io after it has loaded - glTF2ExportUserExtension = gltf_exporter.glTF2ExportUserExtension glTF2_pre_export_callback = gltf_exporter.glTF2_pre_export_callback glTF2_post_export_callback = gltf_exporter.glTF2_post_export_callback - if bpy.app.version > (3, 0, 0): glTF2ImportUserExtension = gltf_importer.glTF2ImportUserExtension diff --git a/addons/io_hubs_addon/components/definitions/visible.py b/addons/io_hubs_addon/components/definitions/visible.py index eaccf894..ddb6d425 100644 --- a/addons/io_hubs_addon/components/definitions/visible.py +++ b/addons/io_hubs_addon/components/definitions/visible.py @@ -5,7 +5,8 @@ def update(self, context): - context.object.hide_viewport = not bpy.context.object.hubs_component_visible.visible + if context.object: + context.object.hide_viewport = not context.object.hubs_component_visible.visible class Visible(HubsComponent): diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index ec358113..098db683 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -5,6 +5,10 @@ from .utils import gather_lightmap_texture_info, HUBS_CONFIG +EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] +EXTENSION_VERSION = HUBS_CONFIG["gltfExtensionVersion"] + + def get_version_string(): from .. import (bl_info) return str(bl_info['version'][0]) + '.' + str(bl_info['version'][1]) + '.' + str(bl_info['version'][2]) @@ -68,11 +72,11 @@ def hubs_gather_gltf_hook(self, gltf2_object, export_settings): if not self.properties.enabled or not self.was_used: return - extension_name = HUBS_CONFIG["gltfExtensionName"] + extension_name = EXTENSION_NAME gltf2_object.extensions[extension_name] = self.Extension( name=extension_name, extension={ - "version": HUBS_CONFIG["gltfExtensionVersion"], + "version": EXTENSION_VERSION, "exporterVersion": get_version_string() }, required=False @@ -140,7 +144,7 @@ def add_hubs_components(self, gltf2_object, blender_object, export_settings): registered_hubs_components = get_components_registry() if component_list.items: - extension_name = HUBS_CONFIG["gltfExtensionName"] + extension_name = EXTENSION_NAME component_data = {} for component_item in component_list.items: diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 9342a55e..4c1a331b 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -1,13 +1,35 @@ import bpy from io_scene_gltf2.io.com.gltf2_io_extensions import Extension +from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode +from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial +from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene from .utils import HUBS_CONFIG +EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] + + +def add_hubs_components(gltf2_object, blender_object, import_settings): + if not gltf2_object.extensions or EXTENSION_NAME not in gltf2_object.extensions: + return + + components_data = gltf2_object.extensions[EXTENSION_NAME] + from ..components.components_registry import get_component_by_name + for component_name in components_data.keys(): + component_class = get_component_by_name(component_name) + if component_class: + component_value = components_data[component_name] + component_class.gather_import( + import_settings, blender_object, component_name, component_value) + else: + print('Could not import unsupported component "%s"' % + (component_name)) + class glTF2ImportUserExtension: def __init__(self): self.extensions = [ - Extension(name="MOZ_hubs_components", extension={}, required=True)] + Extension(name=EXTENSION_NAME, extension={}, required=True)] self.properties = bpy.context.scene.hubs_import_properties def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import_settings): @@ -41,26 +63,64 @@ def gather_import_material_after_hook(self, gltf_material, vertex_color, blender gltf_material, blender_mat, import_settings) def add_hubs_components(self, gltf2_object, blender_object, import_settings): - extension_name = HUBS_CONFIG["gltfExtensionName"] - if not gltf2_object.extensions or extension_name not in gltf2_object.extensions: - return + add_hubs_components(gltf2_object, blender_object, import_settings) + + +# import hooks were only recently added to the glTF exporter, so make a custom hook for now +orig_BlenderNode_create_object = BlenderNode.create_object +orig_BlenderMaterial_create = BlenderMaterial.create +orig_BlenderScene_create = BlenderScene.create + + +@staticmethod +def patched_BlenderNode_create_object(gltf, vnode_id): + blender_object = orig_BlenderNode_create_object(gltf, vnode_id) + + vnode = gltf.vnodes[vnode_id] + node = None + + if vnode.camera_node_idx is not None: + parent_vnode = gltf.vnodes[vnode.parent] + if parent_vnode.name: + node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] + + else: + if vnode.name: + node = [n for n in gltf.data.nodes if n.name == vnode.name][0] + + add_hubs_components(node, vnode.blender_object, gltf) + + return blender_object + + +@staticmethod +def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): + orig_BlenderMaterial_create( + gltf, material_idx, vertex_color) + gltf_material = gltf.data.materials[material_idx] + blender_object = bpy.data.materials[gltf_material.blender_material[None]] + add_hubs_components(gltf_material, blender_object, gltf) + - components_data = gltf2_object.extensions[extension_name] - from ..components.components_registry import get_component_by_name - for component_name in components_data.keys(): - component_class = get_component_by_name(component_name) - if component_class: - component_value = components_data[component_name] - component_class.gather_import( - import_settings, blender_object, component_name, component_value) - else: - print('Could not import unsupported component "%s"' % - (component_name)) +@staticmethod +def patched_BlenderScene_create(gltf): + orig_BlenderScene_create(gltf) + gltf_scene = gltf.data.scenes[gltf.data.scene] + blender_object = bpy.data.scenes[gltf.blender_scene] + add_hubs_components(gltf_scene, blender_object, gltf) def register(): print("Register GLTF Exporter") + if bpy.app.version < (3, 0, 0): + BlenderNode.create_object = patched_BlenderNode_create_object + BlenderMaterial.create = patched_BlenderMaterial_create + BlenderScene.create = patched_BlenderScene_create def unregister(): print("Unregister GLTF Exporter") + if bpy.app.version < (3, 0, 0): + BlenderNode.create_object = orig_BlenderNode_create_object + BlenderMaterial.create = orig_BlenderMaterial_create + BlenderScene.create = orig_BlenderScene_create diff --git a/addons/io_hubs_addon/io/gltf_importer_compat.py b/addons/io_hubs_addon/io/gltf_importer_compat.py deleted file mode 100644 index 05a42de2..00000000 --- a/addons/io_hubs_addon/io/gltf_importer_compat.py +++ /dev/null @@ -1,81 +0,0 @@ -import bpy -from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode -from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial -from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene -from .utils import HUBS_CONFIG - -# import hooks were only recently added to the glTF exporter, so make a custom hook for now -orig_BlenderNode_create_object = BlenderNode.create_object -orig_BlenderMaterial_create = BlenderMaterial.create -orig_BlenderScene_create = BlenderScene.create - -EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] - - -def add_hubs_components(gltf2_object, blender_object, import_settings): - if not gltf2_object.extensions or EXTENSION_NAME not in gltf2_object.extensions: - return - - components_data = gltf2_object.extensions[EXTENSION_NAME] - from ..components.components_registry import get_component_by_name - for component_name in components_data.keys(): - component_class = get_component_by_name(component_name) - if component_class: - component_value = components_data[component_name] - component_class.gather_import( - import_settings, blender_object, component_name, component_value) - else: - print('Could not import unsupported component "%s"' % - (component_name)) - - -@staticmethod -def patched_BlenderNode_create_object(gltf, vnode_id): - blender_object = orig_BlenderNode_create_object(gltf, vnode_id) - - vnode = gltf.vnodes[vnode_id] - node = None - - if vnode.camera_node_idx is not None: - parent_vnode = gltf.vnodes[vnode.parent] - if parent_vnode.name: - node = [n for n in gltf.data.nodes if n.name == parent_vnode.name][0] - - else: - if vnode.name: - node = [n for n in gltf.data.nodes if n.name == vnode.name][0] - - add_hubs_components(node, vnode.blender_object, gltf) - - return blender_object - - -@staticmethod -def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): - orig_BlenderMaterial_create( - gltf, material_idx, vertex_color) - gltf_material = gltf.data.materials[material_idx] - blender_object = bpy.data.materials[gltf_material.blender_material[None]] - add_hubs_components(gltf_material, blender_object, gltf) - - -@staticmethod -def patched_BlenderScene_create(gltf): - orig_BlenderScene_create(gltf) - gltf_scene = gltf.data.scenes[gltf.data.scene] - blender_object = bpy.data.scenes[gltf.blender_scene] - add_hubs_components(gltf_scene, blender_object, gltf) - - -def register(): - print("Register GLTF Importer") - BlenderNode.create_object = patched_BlenderNode_create_object - BlenderMaterial.create = patched_BlenderMaterial_create - BlenderScene.create = patched_BlenderScene_create - - -def unregister(): - print("Unregister GLTF Importer") - BlenderNode.create_object = orig_BlenderNode_create_object - BlenderMaterial.create = orig_BlenderMaterial_create - BlenderScene.create = orig_BlenderScene_create From f8cbf4a3a2664b0bb92afb65841aceb8d7487839 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 28 Jul 2022 15:40:48 +0200 Subject: [PATCH 17/43] Fix media-frame yup issues and expose a global import property for yup --- .../components/definitions/media_frame.py | 19 +++++++++++++++++++ addons/io_hubs_addon/io/gltf_exporter.py | 1 + addons/io_hubs_addon/io/gltf_importer.py | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/addons/io_hubs_addon/components/definitions/media_frame.py b/addons/io_hubs_addon/components/definitions/media_frame.py index feebf515..e10740c6 100644 --- a/addons/io_hubs_addon/components/definitions/media_frame.py +++ b/addons/io_hubs_addon/components/definitions/media_frame.py @@ -8,6 +8,7 @@ from ..utils import V_S1 from .networked import migrate_networked from mathutils import Matrix, Vector +from ...io.utils import import_component, assign_property def is_bone(ob): @@ -178,3 +179,21 @@ def draw(self, context, layout, panel_type): if hasattr(parent, 'parent_bone') and parent.parent_bone: parents.insert(0, parent.parent.pose.bones[parent.parent_bone]) + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = import_component( + component_name, blender_object) + + for property_name, property_value in component_value.items(): + gltf_yup = True + if 'gltf_yup' in import_settings.import_settings: + gltf_yup = import_settings.import_settings['gltf_yup'] + if property_name == 'bounds' and gltf_yup: + bounds = (property_value['x'], + property_value['z'], property_value['y']) + assign_property(import_settings.vnodes, blender_component, + property_name, bounds) + else: + assign_property(import_settings.vnodes, blender_component, + property_name, property_value) diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index 098db683..ea028ea4 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -86,6 +86,7 @@ def hubs_gather_gltf_hook(self, gltf2_object, export_settings): gltf2_object.asset.extras = {} gltf2_object.asset.extras["HUBS_blenderExporterVersion"] = get_version_string( ) + gltf2_object.asset.extras["gltf_yup"] = export_settings['gltf_yup'] def gather_scene_hook(self, gltf2_object, blender_scene, export_settings): if not self.properties.enabled: diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 4c1a331b..8fd7c837 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -32,6 +32,15 @@ def __init__(self): Extension(name=EXTENSION_NAME, extension={}, required=True)] self.properties = bpy.context.scene.hubs_import_properties + def gather_import_scene_before_hook(self, gltf_scene, blender_scene, import_settings): + if not self.properties.enabled: + return + + if import_settings.data.asset and import_settings.data.asset.extras: + if 'gltf_yup' in import_settings.data.asset.extras: + import_settings.import_settings['gltf_yup'] = import_settings.data.asset.extras[ + 'gltf_yup'] + def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import_settings): if not self.properties.enabled: return From 2013a46b6da38cc8ce4933ce9c48c895d9c680bc Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 28 Jul 2022 15:42:43 +0200 Subject: [PATCH 18/43] Remove debug print --- addons/io_hubs_addon/components/definitions/audio_target.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/io_hubs_addon/components/definitions/audio_target.py b/addons/io_hubs_addon/components/definitions/audio_target.py index da4ae5c9..77b9af19 100644 --- a/addons/io_hubs_addon/components/definitions/audio_target.py +++ b/addons/io_hubs_addon/components/definitions/audio_target.py @@ -171,5 +171,4 @@ def gather_import(cls, import_settings, blender_object, component_name, componen import_settings.vnodes[property_value['index']].blender_object) else: - print(f"{property_name} = {property_value}") setattr(blender_component, property_name, property_value) From 1a3a50dcb3ad939468f24eaa8138fa64f8fd0e7e Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 29 Jul 2022 12:21:43 +0200 Subject: [PATCH 19/43] Lightmap support --- .../definitions/environment_settings.py | 11 +++--- addons/io_hubs_addon/io/gltf_importer.py | 35 +++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/environment_settings.py b/addons/io_hubs_addon/components/definitions/environment_settings.py index e93cba40..9c2b11b4 100644 --- a/addons/io_hubs_addon/components/definitions/environment_settings.py +++ b/addons/io_hubs_addon/components/definitions/environment_settings.py @@ -89,12 +89,11 @@ def gather_import(cls, import_settings, blender_object, component_name, componen else: source = gltf_texture.source - if source is not None and source not in import_settings.data.images: - BlenderImage.create( - import_settings, source) - pyimg = import_settings.data.images[source] - blender_image_name = pyimg.blender_image_name - images[source] = blender_image_name + BlenderImage.create( + import_settings, source) + pyimg = import_settings.data.images[source] + blender_image_name = pyimg.blender_image_name + images[source] = blender_image_name for property_name, property_value in component_value.items(): if isinstance(property_value, dict) and property_value['__mhc_link_type'] == "texture": diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 8fd7c837..3d816d91 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -3,6 +3,7 @@ from io_scene_gltf2.blender.imp.gltf2_blender_node import BlenderNode from io_scene_gltf2.blender.imp.gltf2_blender_material import BlenderMaterial from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene +from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage from .utils import HUBS_CONFIG EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] @@ -25,6 +26,32 @@ def add_hubs_components(gltf2_object, blender_object, import_settings): (component_name)) +def add_lightmap(gltf_material, blender_mat, import_settings): + if gltf_material.extensions and 'MOZ_lightmap' in gltf_material.extensions: + extension = gltf_material.extensions['MOZ_lightmap'] + + index = extension['index'] + + BlenderImage.create( + import_settings, index) + pyimg = import_settings.data.images[index] + blender_image_name = pyimg.blender_image_name + blender_image = bpy.data.images[blender_image_name] + blender_image.colorspace_settings.name = "Linear" + blender_mat.use_nodes = True + + nodes = blender_mat.node_tree.nodes + lightmap_node = nodes.new('moz_lightmap.node') + lightmap_node.location = (-300, 0) + lightmap_node.intensity = extension['intensity'] + node_tex = nodes.new('ShaderNodeTexImage') + node_tex.image = blender_image + node_tex.location = (-600, 0) + + blender_mat.node_tree.links.new( + node_tex.outputs["Color"], lightmap_node.inputs["Lightmap"]) + + class glTF2ImportUserExtension: def __init__(self): @@ -71,6 +98,8 @@ def gather_import_material_after_hook(self, gltf_material, vertex_color, blender self.add_hubs_components( gltf_material, blender_mat, import_settings) + add_lightmap(gltf_material, blender_mat, import_settings) + def add_hubs_components(self, gltf2_object, blender_object, import_settings): add_hubs_components(gltf2_object, blender_object, import_settings) @@ -107,8 +136,10 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): orig_BlenderMaterial_create( gltf, material_idx, vertex_color) gltf_material = gltf.data.materials[material_idx] - blender_object = bpy.data.materials[gltf_material.blender_material[None]] - add_hubs_components(gltf_material, blender_object, gltf) + blender_mat = bpy.data.materials[gltf_material.blender_material[None]] + add_hubs_components(gltf_material, blender_mat, gltf) + + add_lightmap(gltf_material, blender_mat, gltf) @staticmethod From a79ce27c7c1bfb149ff0385de7d182d0e14cfeae Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Fri, 29 Jul 2022 15:12:22 +0200 Subject: [PATCH 20/43] Support for importing components in bones --- addons/io_hubs_addon/io/gltf_importer.py | 77 ++++++++++++++++++------ 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 3d816d91..eac946b4 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -8,26 +8,26 @@ EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] +armatures = [] -def add_hubs_components(gltf2_object, blender_object, import_settings): - if not gltf2_object.extensions or EXTENSION_NAME not in gltf2_object.extensions: - return - components_data = gltf2_object.extensions[EXTENSION_NAME] - from ..components.components_registry import get_component_by_name - for component_name in components_data.keys(): - component_class = get_component_by_name(component_name) - if component_class: - component_value = components_data[component_name] - component_class.gather_import( - import_settings, blender_object, component_name, component_value) - else: - print('Could not import unsupported component "%s"' % - (component_name)) +def add_hubs_components(gltf_node, blender_object, import_settings): + if gltf_node and gltf_node.extensions and EXTENSION_NAME in gltf_node.extensions: + components_data = gltf_node.extensions[EXTENSION_NAME] + from ..components.components_registry import get_component_by_name + for component_name in components_data.keys(): + component_class = get_component_by_name(component_name) + if component_class: + component_value = components_data[component_name] + component_class.gather_import( + import_settings, blender_object, component_name, component_value) + else: + print('Could not import unsupported component "%s"' % + (component_name)) def add_lightmap(gltf_material, blender_mat, import_settings): - if gltf_material.extensions and 'MOZ_lightmap' in gltf_material.extensions: + if gltf_material and gltf_material.extensions and 'MOZ_lightmap' in gltf_material.extensions: extension = gltf_material.extensions['MOZ_lightmap'] index = extension['index'] @@ -52,6 +52,17 @@ def add_lightmap(gltf_material, blender_mat, import_settings): node_tex.outputs["Color"], lightmap_node.inputs["Lightmap"]) +def add_bones(import_settings): + # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects + global armatures + for blender_object in armatures: + for bone in blender_object.data.bones: + gltf_bone = next(( + gltf_node for gltf_node in import_settings.data.nodes if gltf_node.name == bone.name), None) + add_hubs_components( + gltf_bone, bone, import_settings) + + class glTF2ImportUserExtension: def __init__(self): @@ -63,6 +74,9 @@ def gather_import_scene_before_hook(self, gltf_scene, blender_scene, import_sett if not self.properties.enabled: return + global armatures + armatures.clear() + if import_settings.data.asset and import_settings.data.asset.extras: if 'gltf_yup' in import_settings.data.asset.extras: import_settings.import_settings['gltf_yup'] = import_settings.data.asset.extras[ @@ -74,6 +88,10 @@ def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import self.add_hubs_components(gltf_scene, blender_scene, import_settings) + # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects + add_bones(import_settings) + armatures.clear() + def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import_settings): if not self.properties.enabled: return @@ -81,6 +99,12 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import self.add_hubs_components( gltf_node, blender_object, import_settings) + # Node hooks are not called for bones. Bones are created together with their armature. + # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. + if vnode.is_arma: + global armatures + armatures.append(blender_object) + def gather_import_image_after_hook(self, gltf_img, blender_image, import_settings): # As of Blender 3.2.0 the importer doesn't import images that are not referenced by a material socket. # We handle this case by case in each component's gather_import override. @@ -100,8 +124,8 @@ def gather_import_material_after_hook(self, gltf_material, vertex_color, blender add_lightmap(gltf_material, blender_mat, import_settings) - def add_hubs_components(self, gltf2_object, blender_object, import_settings): - add_hubs_components(gltf2_object, blender_object, import_settings) + def add_hubs_components(self, gltf_node, blender_object, import_settings): + add_hubs_components(gltf_node, blender_object, import_settings) # import hooks were only recently added to the glTF exporter, so make a custom hook for now @@ -110,7 +134,7 @@ def add_hubs_components(self, gltf2_object, blender_object, import_settings): orig_BlenderScene_create = BlenderScene.create -@staticmethod +@ staticmethod def patched_BlenderNode_create_object(gltf, vnode_id): blender_object = orig_BlenderNode_create_object(gltf, vnode_id) @@ -128,10 +152,16 @@ def patched_BlenderNode_create_object(gltf, vnode_id): add_hubs_components(node, vnode.blender_object, gltf) + # Node hooks are not called for bones. Bones are created together with their armature. + # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. + if vnode.is_arma: + global armatures + armatures.append(vnode.blender_object) + return blender_object -@staticmethod +@ staticmethod def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): orig_BlenderMaterial_create( gltf, material_idx, vertex_color) @@ -142,13 +172,20 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): add_lightmap(gltf_material, blender_mat, gltf) -@staticmethod +@ staticmethod def patched_BlenderScene_create(gltf): + global armatures + armatures.clear() + orig_BlenderScene_create(gltf) gltf_scene = gltf.data.scenes[gltf.data.scene] blender_object = bpy.data.scenes[gltf.blender_scene] add_hubs_components(gltf_scene, blender_object, gltf) + # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects + add_bones(gltf) + armatures.clear() + def register(): print("Register GLTF Exporter") From 0480312010904356b0dbf09c2886b03efaf1d3de Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:35:26 +0200 Subject: [PATCH 21/43] Remove duplicated comment --- addons/io_hubs_addon/io/gltf_importer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index eac946b4..9b4e0768 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -88,7 +88,6 @@ def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import self.add_hubs_components(gltf_scene, blender_scene, import_settings) - # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects add_bones(import_settings) armatures.clear() From b7c95a83bb738fee8698a11b1e8706a06ea231ac Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:45:13 +0200 Subject: [PATCH 22/43] Remove unnecessary gather_imports --- .../components/definitions/audio_target.py | 13 ------------- .../components/definitions/video_texture_target.py | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/audio_target.py b/addons/io_hubs_addon/components/definitions/audio_target.py index 77b9af19..bacd5df8 100644 --- a/addons/io_hubs_addon/components/definitions/audio_target.py +++ b/addons/io_hubs_addon/components/definitions/audio_target.py @@ -159,16 +159,3 @@ def gather(self, export_settings, object): 'minDelay': self.minDelay, 'debug': self.debug } - - @classmethod - def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = import_component( - component_name, blender_object) - - for property_name, property_value in component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, - import_settings.vnodes[property_value['index']].blender_object) - - else: - setattr(blender_component, property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/video_texture_target.py b/addons/io_hubs_addon/components/definitions/video_texture_target.py index d0aafb99..d8320f8d 100644 --- a/addons/io_hubs_addon/components/definitions/video_texture_target.py +++ b/addons/io_hubs_addon/components/definitions/video_texture_target.py @@ -150,16 +150,3 @@ def gather(self, export_settings, object): 'srcNode': gather_joint_property(export_settings, self.srcNode, self, 'bone') if self.bone_id != BLANK_ID else gather_node_property( export_settings, object, self, 'srcNode'), } - - @classmethod - def gather_import(cls, import_settings, blender_object, component_name, component_value): - blender_component = import_component( - component_name, blender_object) - - for property_name, property_value in component_value.items(): - if property_name == 'srcNode': - setattr(blender_component, property_name, - import_settings.vnodes[property_value['index']].blender_object) - - else: - setattr(blender_component, property_name, property_value) From b88f0dce4b847fb78ff62901af0df34124796d4e Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:47:51 +0200 Subject: [PATCH 23/43] Update addons/io_hubs_addon/components/definitions/media_frame.py Co-authored-by: Exairnous --- .../components/definitions/media_frame.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/media_frame.py b/addons/io_hubs_addon/components/definitions/media_frame.py index e10740c6..d2ff449e 100644 --- a/addons/io_hubs_addon/components/definitions/media_frame.py +++ b/addons/io_hubs_addon/components/definitions/media_frame.py @@ -185,15 +185,11 @@ def gather_import(cls, import_settings, blender_object, component_name, componen blender_component = import_component( component_name, blender_object) + gltf_yup = import_settings.import_settings.get('gltf_yup', True) + for property_name, property_value in component_value.items(): - gltf_yup = True - if 'gltf_yup' in import_settings.import_settings: - gltf_yup = import_settings.import_settings['gltf_yup'] if property_name == 'bounds' and gltf_yup: - bounds = (property_value['x'], - property_value['z'], property_value['y']) - assign_property(import_settings.vnodes, blender_component, - property_name, bounds) - else: - assign_property(import_settings.vnodes, blender_component, + property_value['y'], property_value['z'] = property_value['z'], property_value['y'] + + assign_property(import_settings.vnodes, blender_component, property_name, property_value) From abdfc63f8e0dba9f3d3dad74438f0c3785827beb Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:51:49 +0200 Subject: [PATCH 24/43] Update io add_hubs_components function name --- addons/io_hubs_addon/io/gltf_exporter.py | 12 +++++++----- addons/io_hubs_addon/io/gltf_importer.py | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index ea028ea4..308371ca 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -98,7 +98,8 @@ def gather_scene_hook(self, gltf2_object, blender_scene, export_settings): if key.startswith("hubs_"): del gltf2_object.extras[key] - self.add_hubs_components(gltf2_object, blender_scene, export_settings) + self.export_hubs_components( + gltf2_object, blender_scene, export_settings) def gather_node_hook(self, gltf2_object, blender_object, export_settings): if not self.properties.enabled: @@ -110,13 +111,14 @@ def gather_node_hook(self, gltf2_object, blender_object, export_settings): if key.startswith("hubs_"): del gltf2_object.extras[key] - self.add_hubs_components(gltf2_object, blender_object, export_settings) + self.export_hubs_components( + gltf2_object, blender_object, export_settings) def gather_material_hook(self, gltf2_object, blender_material, export_settings): if not self.properties.enabled: return - self.add_hubs_components( + self.export_hubs_components( gltf2_object, blender_material, export_settings) if blender_material.node_tree and blender_material.use_nodes: @@ -136,10 +138,10 @@ def gather_material_unlit_hook(self, gltf2_object, blender_material, export_sett def gather_joint_hook(self, gltf2_object, blender_pose_bone, export_settings): if not self.properties.enabled: return - self.add_hubs_components( + self.export_hubs_components( gltf2_object, blender_pose_bone.bone, export_settings) - def add_hubs_components(self, gltf2_object, blender_object, export_settings): + def export_hubs_components(self, gltf2_object, blender_object, export_settings): component_list = blender_object.hubs_component_list registered_hubs_components = get_components_registry() diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 9b4e0768..a5713464 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -11,7 +11,7 @@ armatures = [] -def add_hubs_components(gltf_node, blender_object, import_settings): +def import_hubs_components(gltf_node, blender_object, import_settings): if gltf_node and gltf_node.extensions and EXTENSION_NAME in gltf_node.extensions: components_data = gltf_node.extensions[EXTENSION_NAME] from ..components.components_registry import get_component_by_name @@ -59,7 +59,7 @@ def add_bones(import_settings): for bone in blender_object.data.bones: gltf_bone = next(( gltf_node for gltf_node in import_settings.data.nodes if gltf_node.name == bone.name), None) - add_hubs_components( + import_hubs_components( gltf_bone, bone, import_settings) @@ -86,7 +86,7 @@ def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import if not self.properties.enabled: return - self.add_hubs_components(gltf_scene, blender_scene, import_settings) + self.import_hubs_components(gltf_scene, blender_scene, import_settings) add_bones(import_settings) armatures.clear() @@ -95,7 +95,7 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import if not self.properties.enabled: return - self.add_hubs_components( + self.import_hubs_components( gltf_node, blender_object, import_settings) # Node hooks are not called for bones. Bones are created together with their armature. @@ -118,13 +118,13 @@ def gather_import_material_after_hook(self, gltf_material, vertex_color, blender if not self.properties.enabled: return - self.add_hubs_components( + self.import_hubs_components( gltf_material, blender_mat, import_settings) add_lightmap(gltf_material, blender_mat, import_settings) - def add_hubs_components(self, gltf_node, blender_object, import_settings): - add_hubs_components(gltf_node, blender_object, import_settings) + def import_hubs_components(self, gltf_node, blender_object, import_settings): + import_hubs_components(gltf_node, blender_object, import_settings) # import hooks were only recently added to the glTF exporter, so make a custom hook for now @@ -149,7 +149,7 @@ def patched_BlenderNode_create_object(gltf, vnode_id): if vnode.name: node = [n for n in gltf.data.nodes if n.name == vnode.name][0] - add_hubs_components(node, vnode.blender_object, gltf) + import_hubs_components(node, vnode.blender_object, gltf) # Node hooks are not called for bones. Bones are created together with their armature. # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. @@ -166,7 +166,7 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): gltf, material_idx, vertex_color) gltf_material = gltf.data.materials[material_idx] blender_mat = bpy.data.materials[gltf_material.blender_material[None]] - add_hubs_components(gltf_material, blender_mat, gltf) + import_hubs_components(gltf_material, blender_mat, gltf) add_lightmap(gltf_material, blender_mat, gltf) @@ -179,7 +179,7 @@ def patched_BlenderScene_create(gltf): orig_BlenderScene_create(gltf) gltf_scene = gltf.data.scenes[gltf.data.scene] blender_object = bpy.data.scenes[gltf.blender_scene] - add_hubs_components(gltf_scene, blender_object, gltf) + import_hubs_components(gltf_scene, blender_object, gltf) # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects add_bones(gltf) From 29f57dbcf2bcfcd8da427bd16fb8a212a54ea594 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:53:09 +0200 Subject: [PATCH 25/43] Update addons/io_hubs_addon/io/gltf_importer.py Co-authored-by: Exairnous --- addons/io_hubs_addon/io/gltf_importer.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index eac946b4..c6057461 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -55,10 +55,9 @@ def add_lightmap(gltf_material, blender_mat, import_settings): def add_bones(import_settings): # Bones are created after the armatures so we need to wait until all nodes have been processed to be able to access the bones objects global armatures - for blender_object in armatures: - for bone in blender_object.data.bones: - gltf_bone = next(( - gltf_node for gltf_node in import_settings.data.nodes if gltf_node.name == bone.name), None) + for armature in armatures.values(): + blender_object = armature['armature'] + for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data. add_hubs_components( gltf_bone, bone, import_settings) From 07c9bc3fa10b2e78d2dda2226fe560d105ae51be Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:53:40 +0200 Subject: [PATCH 26/43] Update addons/io_hubs_addon/io/gltf_importer.py Co-authored-by: Exairnous --- addons/io_hubs_addon/io/gltf_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index c6057461..9ce90424 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -102,7 +102,7 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: global armatures - armatures.append(blender_object) + armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [import_settings.data.nodes[child_index] for child_index in vnode.children if import_settings.vnodes[child_index].type == vnode.Bone]} def gather_import_image_after_hook(self, gltf_img, blender_image, import_settings): # As of Blender 3.2.0 the importer doesn't import images that are not referenced by a material socket. From ee38a929b7cdfc9d66d8ba2588de45a9521a2347 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:53:54 +0200 Subject: [PATCH 27/43] Update addons/io_hubs_addon/io/gltf_importer.py Co-authored-by: Exairnous --- addons/io_hubs_addon/io/gltf_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 9ce90424..044e6f49 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -155,7 +155,7 @@ def patched_BlenderNode_create_object(gltf, vnode_id): # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: global armatures - armatures.append(vnode.blender_object) + armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [gltf.data.nodes[child_index] for child_index in vnode.children if gltf.vnodes[child_index].type == vnode.Bone]} return blender_object From bb12ef3f6a8cc707ebebb92be24854d002a6056f Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 13:59:46 +0200 Subject: [PATCH 28/43] Fix glTF string --- addons/io_hubs_addon/__init__.py | 2 +- addons/io_hubs_addon/components/hubs_component.py | 2 +- addons/io_hubs_addon/io/gltf_exporter.py | 4 ++-- addons/io_hubs_addon/io/gltf_importer.py | 4 ++-- addons/io_hubs_addon/io/utils.py | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/io_hubs_addon/__init__.py b/addons/io_hubs_addon/__init__.py index 6171c9c3..5b23449c 100644 --- a/addons/io_hubs_addon/__init__.py +++ b/addons/io_hubs_addon/__init__.py @@ -5,7 +5,7 @@ bl_info = { "name": "Hubs Blender Addon", "author": "Mozilla Hubs", - "description": "Tools for developing GLTF assets for Mozilla Hubs", + "description": "Tools for developing glTF assets for Mozilla Hubs", "blender": (3, 1, 2), "version": (1, 0, 0), "location": "", diff --git a/addons/io_hubs_addon/components/hubs_component.py b/addons/io_hubs_addon/components/hubs_component.py index 8d03b840..10417486 100644 --- a/addons/io_hubs_addon/components/hubs_component.py +++ b/addons/io_hubs_addon/components/hubs_component.py @@ -6,7 +6,7 @@ class HubsComponent(PropertyGroup): _definition = { - # The name that will be used in the GLTF file MOZ_hubs_components object when exporting the component. + # The name that will be used in the glTF file MOZ_hubs_components object when exporting the component. 'name': 'template', # Name to be used in the panels, if not set the component name will be used 'display_name': 'Hubs Component Template', diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index 308371ca..73c60ddc 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -174,10 +174,10 @@ def export_hubs_components(self, gltf2_object, blender_object, export_settings): def register(): - print("Register GLTF Exporter") + print("Register glTF Exporter") gltf2_blender_export.__gather_gltf = patched_gather_gltf def unregister(): - print("Unregister GLTF Exporter") + print("Unregister glTF Exporter") gltf2_blender_export.__gather_gltf = orig_gather_gltf diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index a5713464..b886abaf 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -187,7 +187,7 @@ def patched_BlenderScene_create(gltf): def register(): - print("Register GLTF Exporter") + print("Register glTF Importer") if bpy.app.version < (3, 0, 0): BlenderNode.create_object = patched_BlenderNode_create_object BlenderMaterial.create = patched_BlenderMaterial_create @@ -195,7 +195,7 @@ def register(): def unregister(): - print("Unregister GLTF Exporter") + print("Unregister glTF Importer") if bpy.app.version < (3, 0, 0): BlenderNode.create_object = orig_BlenderNode_create_object BlenderMaterial.create = orig_BlenderMaterial_create diff --git a/addons/io_hubs_addon/io/utils.py b/addons/io_hubs_addon/io/utils.py index 43db9ebc..90fe32e3 100644 --- a/addons/io_hubs_addon/io/utils.py +++ b/addons/io_hubs_addon/io/utils.py @@ -301,7 +301,7 @@ def gather_texture_property(export_settings, blender_object, target, property_na def gather_color_property(export_settings, object, component, property_name): - # Convert RGB color array to hex. Blender stores colors in linear space and GLTF color factors are typically in linear space + # Convert RGB color array to hex. Blender stores colors in linear space and glTF color factors are typically in linear space c = getattr(component, property_name) return "#{0:02x}{1:02x}{2:02x}".format(max(0, min(int(c[0] * 256.0), 255)), max(0, min(int(c[1] * 256.0), 255)), max(0, min(int(c[2] * 256.0), 255))) From eab32822d8f1cd6970d138e724b4b6e7cb77cbfe Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:00:08 +0200 Subject: [PATCH 29/43] Remove import_hubs_components method --- addons/io_hubs_addon/io/gltf_importer.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index b886abaf..826ad008 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -86,7 +86,7 @@ def gather_import_scene_after_nodes_hook(self, gltf_scene, blender_scene, import if not self.properties.enabled: return - self.import_hubs_components(gltf_scene, blender_scene, import_settings) + import_hubs_components(gltf_scene, blender_scene, import_settings) add_bones(import_settings) armatures.clear() @@ -95,7 +95,7 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import if not self.properties.enabled: return - self.import_hubs_components( + import_hubs_components( gltf_node, blender_object, import_settings) # Node hooks are not called for bones. Bones are created together with their armature. @@ -118,14 +118,11 @@ def gather_import_material_after_hook(self, gltf_material, vertex_color, blender if not self.properties.enabled: return - self.import_hubs_components( + import_hubs_components( gltf_material, blender_mat, import_settings) add_lightmap(gltf_material, blender_mat, import_settings) - def import_hubs_components(self, gltf_node, blender_object, import_settings): - import_hubs_components(gltf_node, blender_object, import_settings) - # import hooks were only recently added to the glTF exporter, so make a custom hook for now orig_BlenderNode_create_object = BlenderNode.create_object From 4cf0b7f5f1ef94738101cc9ab391adcc53af0e10 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:03:05 +0200 Subject: [PATCH 30/43] Catch and log component import exceptions --- addons/io_hubs_addon/io/gltf_importer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 826ad008..2bedae1d 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -19,8 +19,11 @@ def import_hubs_components(gltf_node, blender_object, import_settings): component_class = get_component_by_name(component_name) if component_class: component_value = components_data[component_name] - component_class.gather_import( - import_settings, blender_object, component_name, component_value) + try: + component_class.gather_import( + import_settings, blender_object, component_name, component_value) + except Exception as err: + print(err) else: print('Could not import unsupported component "%s"' % (component_name)) From 87d1bc9d76c799726f3ab3952ba81ff605206ea6 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:05:47 +0200 Subject: [PATCH 31/43] Move import --- addons/io_hubs_addon/io/gltf_importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 2bedae1d..dcf1eb93 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -5,6 +5,7 @@ from io_scene_gltf2.blender.imp.gltf2_blender_scene import BlenderScene from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage from .utils import HUBS_CONFIG +from ..components.components_registry import get_component_by_name EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] @@ -14,7 +15,6 @@ def import_hubs_components(gltf_node, blender_object, import_settings): if gltf_node and gltf_node.extensions and EXTENSION_NAME in gltf_node.extensions: components_data = gltf_node.extensions[EXTENSION_NAME] - from ..components.components_registry import get_component_by_name for component_name in components_data.keys(): component_class = get_component_by_name(component_name) if component_class: From 64e12023cad5fad8c1f23ade91604e1af9b0e4bc Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:07:25 +0200 Subject: [PATCH 32/43] Update addons/io_hubs_addon/components/definitions/background.py Co-authored-by: Exairnous --- addons/io_hubs_addon/components/definitions/background.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/background.py b/addons/io_hubs_addon/components/definitions/background.py index 10a0cb8d..ce658728 100644 --- a/addons/io_hubs_addon/components/definitions/background.py +++ b/addons/io_hubs_addon/components/definitions/background.py @@ -14,6 +14,5 @@ class EnvironmentSettings(HubsComponent): def gather_import(cls, import_settings, blender_object, component_name, component_value): blender_component = import_component( 'environemnt-settings', blender_object) - for property_name, property_value in component_value.items(): - assign_property(import_settings.vnodes, blender_component, - property_name, property_value) + blender_component.toneMapping = "LinearToneMapping" + set_color_from_hex(blender_component, "backgroundColor", component_value['color']) From 3f66db01028bfd45190d46e651b91c5308d86870 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:07:41 +0200 Subject: [PATCH 33/43] Update addons/io_hubs_addon/components/definitions/background.py Co-authored-by: Exairnous --- addons/io_hubs_addon/components/definitions/background.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/components/definitions/background.py b/addons/io_hubs_addon/components/definitions/background.py index ce658728..0a3aeb7b 100644 --- a/addons/io_hubs_addon/components/definitions/background.py +++ b/addons/io_hubs_addon/components/definitions/background.py @@ -1,4 +1,4 @@ -from ...io.utils import import_component, assign_property +from ...io.utils import import_component, set_color_from_hex from ..hubs_component import HubsComponent from ..types import NodeType From 03427908014eef826c0ded7c93f9a83131449237 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:08:50 +0200 Subject: [PATCH 34/43] Update addons/io_hubs_addon/io/gltf_importer.py Co-authored-by: Exairnous --- addons/io_hubs_addon/io/gltf_importer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 044e6f49..e939c70f 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -165,7 +165,8 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): orig_BlenderMaterial_create( gltf, material_idx, vertex_color) gltf_material = gltf.data.materials[material_idx] - blender_mat = bpy.data.materials[gltf_material.blender_material[None]] + blender_mat_name = next(iter(gltf_material.blender_material.values())) + blender_mat = bpy.data.materials[blender_mat_name add_hubs_components(gltf_material, blender_mat, gltf) add_lightmap(gltf_material, blender_mat, gltf) From 19c8b083b68c1ea2b4d39d7c4ab2fd2e43d60724 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:16:55 +0200 Subject: [PATCH 35/43] Fix merge issues --- addons/io_hubs_addon/io/gltf_importer.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 8cc01320..a56cbc1a 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -60,7 +60,7 @@ def add_bones(import_settings): global armatures for armature in armatures.values(): blender_object = armature['armature'] - for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data. + for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data): add_hubs_components( gltf_bone, bone, import_settings) @@ -104,7 +104,8 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: global armatures - armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [import_settings.data.nodes[child_index] for child_index in vnode.children if import_settings.vnodes[child_index].type == vnode.Bone]} + armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [ + import_settings.data.nodes[child_index] for child_index in vnode.children if import_settings.vnodes[child_index].type == vnode.Bone]} def gather_import_image_after_hook(self, gltf_img, blender_image, import_settings): # As of Blender 3.2.0 the importer doesn't import images that are not referenced by a material socket. @@ -154,7 +155,8 @@ def patched_BlenderNode_create_object(gltf, vnode_id): # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: global armatures - armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [gltf.data.nodes[child_index] for child_index in vnode.children if gltf.vnodes[child_index].type == vnode.Bone]} + armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [ + gltf.data.nodes[child_index] for child_index in vnode.children if gltf.vnodes[child_index].type == vnode.Bone]} return blender_object @@ -165,8 +167,8 @@ def patched_BlenderMaterial_create(gltf, material_idx, vertex_color): gltf, material_idx, vertex_color) gltf_material = gltf.data.materials[material_idx] blender_mat_name = next(iter(gltf_material.blender_material.values())) - blender_mat = bpy.data.materials[blender_mat_name - add_hubs_components(gltf_material, blender_mat, gltf) + blender_mat = bpy.data.materials[blender_mat_name] + import_hubs_components(gltf_material, blender_mat, gltf) add_lightmap(gltf_material, blender_mat, gltf) From 35610fdda42fcd576b72956788862028c298e1fb Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Mon, 22 Aug 2022 14:42:26 +0200 Subject: [PATCH 36/43] Fix merge issues --- addons/io_hubs_addon/io/gltf_importer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index a56cbc1a..0466d3f2 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -9,7 +9,7 @@ EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] -armatures = [] +armatures = {} def import_hubs_components(gltf_node, blender_object, import_settings): @@ -60,8 +60,8 @@ def add_bones(import_settings): global armatures for armature in armatures.values(): blender_object = armature['armature'] - for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data): - add_hubs_components( + for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data.bones): + import_hubs_components( gltf_bone, bone, import_settings) From 091fd121437f138e202a85104f2e9f3d157ae6f7 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 25 Aug 2022 12:29:13 +0200 Subject: [PATCH 37/43] Fix lightmap import --- addons/io_hubs_addon/io/gltf_importer.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 0466d3f2..614e9a61 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -33,16 +33,24 @@ def add_lightmap(gltf_material, blender_mat, import_settings): if gltf_material and gltf_material.extensions and 'MOZ_lightmap' in gltf_material.extensions: extension = gltf_material.extensions['MOZ_lightmap'] - index = extension['index'] + texture_index = extension['index'] + + gltf_texture = import_settings.data.textures[texture_index] + texture_extensions = gltf_texture.extensions + if texture_extensions and texture_extensions.get('MOZ_texture_rgbe'): + source = gltf_texture.extensions['MOZ_texture_rgbe']['source'] + else: + source = gltf_texture.source BlenderImage.create( - import_settings, index) - pyimg = import_settings.data.images[index] + import_settings, source) + pyimg = import_settings.data.images[source] blender_image_name = pyimg.blender_image_name blender_image = bpy.data.images[blender_image_name] - blender_image.colorspace_settings.name = "Linear" - blender_mat.use_nodes = True + if pyimg.mime_type == "image/vnd.radiance": + blender_image.colorspace_settings.name = "Linear" + blender_mat.use_nodes = True nodes = blender_mat.node_tree.nodes lightmap_node = nodes.new('moz_lightmap.node') lightmap_node.location = (-300, 0) @@ -50,9 +58,13 @@ def add_lightmap(gltf_material, blender_mat, import_settings): node_tex = nodes.new('ShaderNodeTexImage') node_tex.image = blender_image node_tex.location = (-600, 0) - blender_mat.node_tree.links.new( node_tex.outputs["Color"], lightmap_node.inputs["Lightmap"]) + node_uv = nodes.new('ShaderNodeUVMap') + node_uv.uv_map = 'UVMap.%03d' % 1 + node_uv.location = (-900, 0) + blender_mat.node_tree.links.new( + node_uv.outputs["UV"], node_tex.inputs["Vector"]) def add_bones(import_settings): From 021299d24c2512f839007c833c25ca11d08a2651 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 25 Aug 2022 13:50:13 +0200 Subject: [PATCH 38/43] Show importer exception call stack --- addons/io_hubs_addon/io/gltf_importer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 614e9a61..09a41098 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -6,6 +6,7 @@ from io_scene_gltf2.blender.imp.gltf2_blender_image import BlenderImage from .utils import HUBS_CONFIG from ..components.components_registry import get_component_by_name +import traceback EXTENSION_NAME = HUBS_CONFIG["gltfExtensionName"] @@ -22,8 +23,8 @@ def import_hubs_components(gltf_node, blender_object, import_settings): try: component_class.gather_import( import_settings, blender_object, component_name, component_value) - except Exception as err: - print(err) + except Exception: + traceback.print_exc() else: print('Could not import unsupported component "%s"' % (component_name)) From f3a5f8136d3a098e59ba3e8701868cce1523b388 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 25 Aug 2022 13:50:43 +0200 Subject: [PATCH 39/43] Support for Spoke GLB import --- .../components/definitions/spawner.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/addons/io_hubs_addon/components/definitions/spawner.py b/addons/io_hubs_addon/components/definitions/spawner.py index 553cc61a..73cbb8d4 100644 --- a/addons/io_hubs_addon/components/definitions/spawner.py +++ b/addons/io_hubs_addon/components/definitions/spawner.py @@ -2,6 +2,7 @@ from bpy.props import StringProperty, BoolProperty from ..hubs_component import HubsComponent from ..types import Category, PanelType, NodeType +from ...io.utils import import_component, assign_property class Spawner(HubsComponent): @@ -42,3 +43,16 @@ def migrate_data(ob): if ob.type == 'ARMATURE': for bone in ob.data.bones: migrate_data(bone) + + @classmethod + def gather_import(cls, import_settings, blender_object, component_name, component_value): + blender_component = import_component( + component_name, blender_object) + + for property_name, property_value in component_value.items(): + if property_name == 'mediaOptions': + setattr(blender_component, "applyGravity", + property_value["applyGravity"]) + else: + assign_property(import_settings, blender_component, + property_name, property_value) From c2089b556d3aa13ee024a5cc9dd1ede3fd60b33d Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Fri, 26 Aug 2022 04:30:31 -0400 Subject: [PATCH 40/43] Cleanup. Remove unused imports. Rename class to Background background.py. Fix typo in the component name passed to import_component in background.py. Pass vnodes instead of import_settings to assign_property for the Spawner's gather_import (vnodes is what assign_property expects currently). --- addons/io_hubs_addon/components/definitions/audio_target.py | 2 +- addons/io_hubs_addon/components/definitions/background.py | 4 ++-- addons/io_hubs_addon/components/definitions/spawner.py | 2 +- .../components/definitions/video_texture_target.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/io_hubs_addon/components/definitions/audio_target.py b/addons/io_hubs_addon/components/definitions/audio_target.py index bacd5df8..c5000855 100644 --- a/addons/io_hubs_addon/components/definitions/audio_target.py +++ b/addons/io_hubs_addon/components/definitions/audio_target.py @@ -4,7 +4,7 @@ from ..utils import has_component from ..types import Category, PanelType, NodeType from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property, import_component +from ...io.utils import gather_joint_property, gather_node_property BLANK_ID = "374e54CMHFCipSk" diff --git a/addons/io_hubs_addon/components/definitions/background.py b/addons/io_hubs_addon/components/definitions/background.py index 0a3aeb7b..c51875ca 100644 --- a/addons/io_hubs_addon/components/definitions/background.py +++ b/addons/io_hubs_addon/components/definitions/background.py @@ -3,7 +3,7 @@ from ..types import NodeType -class EnvironmentSettings(HubsComponent): +class Background(HubsComponent): _definition = { 'name': 'background', 'display_name': 'Background', @@ -13,6 +13,6 @@ class EnvironmentSettings(HubsComponent): @classmethod def gather_import(cls, import_settings, blender_object, component_name, component_value): blender_component = import_component( - 'environemnt-settings', blender_object) + 'environment-settings', blender_object) blender_component.toneMapping = "LinearToneMapping" set_color_from_hex(blender_component, "backgroundColor", component_value['color']) diff --git a/addons/io_hubs_addon/components/definitions/spawner.py b/addons/io_hubs_addon/components/definitions/spawner.py index 73cbb8d4..4cd0d41f 100644 --- a/addons/io_hubs_addon/components/definitions/spawner.py +++ b/addons/io_hubs_addon/components/definitions/spawner.py @@ -54,5 +54,5 @@ def gather_import(cls, import_settings, blender_object, component_name, componen setattr(blender_component, "applyGravity", property_value["applyGravity"]) else: - assign_property(import_settings, blender_component, + assign_property(import_settings.vnodes, blender_component, property_name, property_value) diff --git a/addons/io_hubs_addon/components/definitions/video_texture_target.py b/addons/io_hubs_addon/components/definitions/video_texture_target.py index d8320f8d..c32f0311 100644 --- a/addons/io_hubs_addon/components/definitions/video_texture_target.py +++ b/addons/io_hubs_addon/components/definitions/video_texture_target.py @@ -3,7 +3,7 @@ from ..types import Category, PanelType, NodeType from ..utils import has_component from bpy.types import Object -from ...io.utils import gather_joint_property, gather_node_property, import_component +from ...io.utils import gather_joint_property, gather_node_property BLANK_ID = "pXph8WBzMu9fung" From ff2bc72e9ead0f604d687695b6111ff046590553 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Tue, 6 Sep 2022 19:15:05 +0200 Subject: [PATCH 41/43] Fix merge conflict --- addons/io_hubs_addon/io/gltf_exporter.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_exporter.py b/addons/io_hubs_addon/io/gltf_exporter.py index 8031cae4..6f52ec60 100644 --- a/addons/io_hubs_addon/io/gltf_exporter.py +++ b/addons/io_hubs_addon/io/gltf_exporter.py @@ -180,19 +180,10 @@ def export_hubs_components(self, gltf2_object, blender_object, export_settings): def register(): print("Register GLTF Exporter") - register_export_panel() if bpy.app.version < (3, 0, 0): gltf2_blender_export.__gather_gltf = patched_gather_gltf - bpy.utils.register_class(HubsComponentsExtensionProperties) - bpy.types.Scene.HubsComponentsExtensionProperties = PointerProperty( - type=HubsComponentsExtensionProperties) - def unregister(): print("Unregister GLTF Exporter") - unregister_export_panel() - del bpy.types.Scene.HubsComponentsExtensionProperties - bpy.utils.unregister_class(HubsComponentsExtensionProperties) if bpy.app.version < (3, 0, 0): gltf2_blender_export.__gather_gltf = orig_gather_gltf - unregister_export_panel() From 01612384ff4538336577a11b0bba935c842ff184 Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Sun, 11 Sep 2022 09:34:19 -0400 Subject: [PATCH 42/43] Use import extensions starting in Blender 3.1 because they aren't present in 3.0. --- addons/io_hubs_addon/io/gltf_importer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index 09a41098..d41eacd3 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -203,7 +203,7 @@ def patched_BlenderScene_create(gltf): def register(): print("Register glTF Importer") - if bpy.app.version < (3, 0, 0): + if bpy.app.version < (3, 1, 0): BlenderNode.create_object = patched_BlenderNode_create_object BlenderMaterial.create = patched_BlenderMaterial_create BlenderScene.create = patched_BlenderScene_create @@ -211,7 +211,7 @@ def register(): def unregister(): print("Unregister glTF Importer") - if bpy.app.version < (3, 0, 0): + if bpy.app.version < (3, 1, 0): BlenderNode.create_object = orig_BlenderNode_create_object BlenderMaterial.create = orig_BlenderMaterial_create BlenderScene.create = orig_BlenderScene_create From 0fb5c34d33c412cd928f9221902068c98c0b3e4b Mon Sep 17 00:00:00 2001 From: Ryan Inch Date: Mon, 19 Sep 2022 01:59:52 -0400 Subject: [PATCH 43/43] Fix #123 This fixes bone components not being imported if they aren't in the top level of the hierarchy. Note: The gltf bones aren't in the same order as the armature bones, this is by design. I considered using the bone order to map the gltf bones to the armature bones (potentially faster), but decided it would be too fragile, and mapping it would have potentially been slower anyway. I loop through the bones in the armature and access the gltf bones by name rather than the other way around because Blender's internal data structures are mostly based on linked lists, so looping over it is much more performant than doing lookups for each item. --- addons/io_hubs_addon/io/gltf_importer.py | 27 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/addons/io_hubs_addon/io/gltf_importer.py b/addons/io_hubs_addon/io/gltf_importer.py index d41eacd3..fcf3d87d 100644 --- a/addons/io_hubs_addon/io/gltf_importer.py +++ b/addons/io_hubs_addon/io/gltf_importer.py @@ -73,11 +73,28 @@ def add_bones(import_settings): global armatures for armature in armatures.values(): blender_object = armature['armature'] - for gltf_bone, bone in zip(armature['gltf_bones'], blender_object.data.bones): + gltf_bones = armature['gltf_bones'] + for bone in blender_object.data.bones: + gltf_bone = gltf_bones[bone.name] import_hubs_components( gltf_bone, bone, import_settings) +def store_bones_for_import(import_settings, vnode): + # Store the glTF bones with the armature so their components can be imported once the Blender bones are created. + global armatures + children = vnode.children[:] + gltf_bones = {} + while children: + child_index = children.pop() + child_vnode = import_settings.vnodes[child_index] + if child_vnode.type == vnode.Bone: + gltf_bones[child_vnode.name] = import_settings.data.nodes[child_index] + children.extend(child_vnode.children) + + armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': gltf_bones} + + class glTF2ImportUserExtension: def __init__(self): @@ -116,9 +133,7 @@ def gather_import_node_after_hook(self, vnode, gltf_node, blender_object, import # Node hooks are not called for bones. Bones are created together with their armature. # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: - global armatures - armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [ - import_settings.data.nodes[child_index] for child_index in vnode.children if import_settings.vnodes[child_index].type == vnode.Bone]} + store_bones_for_import(import_settings, vnode) def gather_import_image_after_hook(self, gltf_img, blender_image, import_settings): # As of Blender 3.2.0 the importer doesn't import images that are not referenced by a material socket. @@ -167,9 +182,7 @@ def patched_BlenderNode_create_object(gltf, vnode_id): # Node hooks are not called for bones. Bones are created together with their armature. # Unfortunately the bones are created after this hook is called so we need to wait until all nodes have been created. if vnode.is_arma: - global armatures - armatures[vnode.blender_object.name] = {'armature': vnode.blender_object, 'gltf_bones': [ - gltf.data.nodes[child_index] for child_index in vnode.children if gltf.vnodes[child_index].type == vnode.Bone]} + store_bones_for_import(gltf, vnode) return blender_object