Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Kim <pk15950@gmail.com>2022-03-15 14:07:23 +0300
committerPeter Kim <pk15950@gmail.com>2022-03-15 14:07:23 +0300
commit3ce8c66917f9d5debdb2e155d2ee0cda76c56860 (patch)
tree4fb3d946c9c3898e4c7fc6072ca97e86e7d3c268
parent96209d6e836f2504390fdcc8410b0a7475668a74 (diff)
parent777653f7d6322a3a651c5ca95ba9f458165b9b48 (diff)
Merge branch 'master' into xr-dev
-rw-r--r--add_curve_extra_objects/add_curve_curly.py6
-rw-r--r--add_curve_extra_objects/beveltaper_curve.py4
-rw-r--r--greasepencil_tools/__init__.py5
-rw-r--r--greasepencil_tools/draw_tools.py23
-rw-r--r--greasepencil_tools/timeline_scrub.py4
-rw-r--r--greasepencil_tools/ui_panels.py15
-rwxr-xr-xio_scene_gltf2/__init__.py47
-rwxr-xr-xio_scene_gltf2/blender/com/gltf2_blender_material_helpers.py9
-rw-r--r--io_scene_gltf2/blender/com/gltf2_blender_ui.py49
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_export.py3
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py160
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py22
-rw-r--r--io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_unlit.py5
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py10
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gather_texture_info.py14
-rw-r--r--io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py11
-rwxr-xr-xio_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py4
-rwxr-xr-xio_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py9
-rwxr-xr-xio_scene_gltf2/io/exp/gltf2_io_export.py19
-rw-r--r--viewport_vr_preview/operators.py2
20 files changed, 332 insertions, 89 deletions
diff --git a/add_curve_extra_objects/add_curve_curly.py b/add_curve_extra_objects/add_curve_curly.py
index 0111aaf6..af02f115 100644
--- a/add_curve_extra_objects/add_curve_curly.py
+++ b/add_curve_extra_objects/add_curve_curly.py
@@ -5,7 +5,7 @@
bl_info = {
"name": "Curly Curves",
"author": "Cmomoney",
- "version": (1, 1, 9),
+ "version": (1, 2, 0),
"blender": (2, 80, 0),
"location": "View3D > Add > Curve > Curly Curve",
"description": "Adds a new Curly Curve",
@@ -402,7 +402,7 @@ def make_curve(self, context, verts, lh, rh):
for p in range(len(verts)):
c = 0
newSpline = Curve.data.splines.new(type='BEZIER') # newSpline
- newSpline.bezier_points.add(len(verts[p]) / 3 - 1)
+ newSpline.bezier_points.add(int(len(verts[p]) / 3 - 1))
newSpline.bezier_points.foreach_set('co', verts[p])
for bp in newSpline.bezier_points:
@@ -424,7 +424,7 @@ def make_curve(self, context, verts, lh, rh):
for p in range(len(verts)):
c = 0
newSpline = dataCurve.splines.new(type='BEZIER') # newSpline
- newSpline.bezier_points.add(len(verts[p]) / 3 - 1)
+ newSpline.bezier_points.add(int(len(verts[p]) / 3 - 1))
newSpline.bezier_points.foreach_set('co', verts[p])
for bp in newSpline.bezier_points:
diff --git a/add_curve_extra_objects/beveltaper_curve.py b/add_curve_extra_objects/beveltaper_curve.py
index 80c01b3a..798b1fbb 100644
--- a/add_curve_extra_objects/beveltaper_curve.py
+++ b/add_curve_extra_objects/beveltaper_curve.py
@@ -5,7 +5,7 @@
bl_info = {
"name": "Bevel/Taper Curve",
"author": "Cmomoney",
- "version": (1, 2),
+ "version": (1, 2, 1),
"blender": (2, 80, 0),
"location": "View3D > Object > Bevel/Taper",
"description": "Adds bevel and/or taper curve to active curve",
@@ -204,7 +204,7 @@ def make_curve(self, context, verts, lh, rh):
c = 0
spline = curve_data.splines.new(type='BEZIER')
spline.use_cyclic_u = True
- spline.bezier_points.add(len(verts[p]) / 3 - 1)
+ spline.bezier_points.add(int(len(verts[p]) / 3 - 1))
spline.bezier_points.foreach_set('co', verts[p])
for bp in spline.bezier_points:
diff --git a/greasepencil_tools/__init__.py b/greasepencil_tools/__init__.py
index 18b808c4..980493ed 100644
--- a/greasepencil_tools/__init__.py
+++ b/greasepencil_tools/__init__.py
@@ -4,7 +4,7 @@ bl_info = {
"name": "Grease Pencil Tools",
"description": "Extra tools for Grease Pencil",
"author": "Samuel Bernou, Antonio Vazquez, Daniel Martinez Lara, Matias Mendiola",
-"version": (1, 5, 6),
+"version": (1, 6, 0),
"blender": (2, 91, 0),
"location": "Sidebar > Grease Pencil > Grease Pencil Tools",
"warning": "",
@@ -20,6 +20,7 @@ from . import (prefs,
line_reshape,
rotate_canvas,
timeline_scrub,
+ draw_tools,
import_brush_pack,
ui_panels,
)
@@ -32,6 +33,7 @@ def register():
box_deform.register()
line_reshape.register()
rotate_canvas.register()
+ draw_tools.register()
import_brush_pack.register()
ui_panels.register()
@@ -43,6 +45,7 @@ def unregister():
return
ui_panels.unregister()
import_brush_pack.unregister()
+ draw_tools.unregister()
rotate_canvas.unregister()
box_deform.unregister()
line_reshape.unregister()
diff --git a/greasepencil_tools/draw_tools.py b/greasepencil_tools/draw_tools.py
new file mode 100644
index 00000000..6d2cf3a9
--- /dev/null
+++ b/greasepencil_tools/draw_tools.py
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import bpy
+
+class GP_OT_camera_flip_x(bpy.types.Operator):
+ bl_idname = "gp.camera_flip_x"
+ bl_label = "Camera Flip X"
+ bl_description = "Invert active camera scale.x to flip view horizontally"
+ bl_options = {"REGISTER"}
+
+ @classmethod
+ def poll(cls, context):
+ return context.space_data.region_3d.view_perspective == 'CAMERA'
+
+ def execute(self, context):
+ context.scene.camera.scale.x *= -1
+ return {"FINISHED"}
+
+def register():
+ bpy.utils.register_class(GP_OT_camera_flip_x)
+
+def unregister():
+ bpy.utils.unregister_class(GP_OT_camera_flip_x)
diff --git a/greasepencil_tools/timeline_scrub.py b/greasepencil_tools/timeline_scrub.py
index 8f058ed9..eaccab99 100644
--- a/greasepencil_tools/timeline_scrub.py
+++ b/greasepencil_tools/timeline_scrub.py
@@ -21,13 +21,13 @@ from bpy.props import (BoolProperty,
EnumProperty)
-def nearest(array, value):
+def nearest(array, value) -> int:
'''
Get a numpy array and a target value
Return closest val found in array to passed value
'''
idx = (np.abs(array - value)).argmin()
- return array[idx]
+ return int(array[idx])
def draw_callback_px(self, context):
diff --git a/greasepencil_tools/ui_panels.py b/greasepencil_tools/ui_panels.py
index ff3900de..2e8a50f1 100644
--- a/greasepencil_tools/ui_panels.py
+++ b/greasepencil_tools/ui_panels.py
@@ -20,15 +20,24 @@ class GP_PT_sidebarPanel(bpy.types.Panel):
layout.operator('gp.straight_stroke', icon ="CURVE_PATH")# IPO_LINEAR
- # Expose Native view operators
- # if context.scene.camera:
+ # Expose native view operators
row = layout.row(align=True)
- row.operator('view3d.zoom_camera_1_to_1', text = 'Zoom 1:1', icon = 'ZOOM_PREVIOUS')# FULLSCREEN_EXIT?
+ row.operator('view3d.zoom_camera_1_to_1', text = 'Zoom 1:1', icon = 'ZOOM_PREVIOUS') # FULLSCREEN_EXIT
row.operator('view3d.view_center_camera', text = 'Zoom Fit', icon = 'FULLSCREEN_ENTER')
+
+ # Rotation save/load
row = layout.row(align=True)
row.operator('view3d.rotate_canvas_reset', text = 'Reset Rotation', icon = 'FILE_REFRESH')
row.operator('view3d.rotate_canvas_set', text = 'Save Rotation', icon = 'DRIVER_ROTATIONAL_DIFFERENCE')
+ # View flip
+ if context.scene.camera and context.scene.camera.scale.x < 0:
+ row = layout.row(align=True)
+ row.operator('gp.camera_flip_x', text = 'Camera Mirror Flip', icon = 'MOD_MIRROR')
+ row.label(text='', icon='LOOP_BACK')
+ else:
+ layout.operator('gp.camera_flip_x', text = 'Camera Mirror Flip', icon = 'MOD_MIRROR')
+
def menu_boxdeform_entry(self, context):
"""Transform shortcut to append in existing menu"""
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index b290f946..fd0687b9 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -4,7 +4,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
- "version": (3, 2, 9),
+ "version": (3, 2, 15),
'blender': (3, 1, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
@@ -287,13 +287,6 @@ class ExportGLTF2_Base:
default=False
)
- # keep it for compatibility (for now)
- export_selected: BoolProperty(
- name='Selected Objects',
- description='Export selected objects only',
- default=False
- )
-
use_selection: BoolProperty(
name='Selected Objects',
description='Export selected objects only',
@@ -462,11 +455,6 @@ class ExportGLTF2_Base:
self.will_save_settings = False
if settings:
try:
- if 'export_selected' in settings.keys(): # Back compatibility for export_selected --> use_selection
- setattr(self, "use_selection", settings['export_selected'])
- settings["use_selection"] = settings['export_selected']
- del settings['export_selected']
- print("export_selected is now renamed use_selection, and will be deleted in a few release")
for (k, v) in settings.items():
setattr(self, k, v)
self.will_save_settings = True
@@ -503,8 +491,6 @@ class ExportGLTF2_Base:
x: getattr(self, x) for x in dir(all_props)
if (x.startswith("export_") or x in exceptional) and all_props.get(x) is not None
}
- if 'export_selected' in export_props.keys():
- del export_props['export_selected'] # Do not save this property, only here for backward compatibility
context.scene[self.scene_key] = export_props
def execute(self, context):
@@ -554,18 +540,12 @@ class ExportGLTF2_Base:
export_settings['gltf_colors'] = self.export_colors
export_settings['gltf_cameras'] = self.export_cameras
- # compatibility after renaming export_selected to use_selection
- if self.export_selected is True:
- self.report({"WARNING"}, "export_selected is now renamed use_selection, and will be deleted in a few release")
- export_settings['gltf_selected'] = self.export_selected
- else:
- export_settings['gltf_selected'] = self.use_selection
export_settings['gltf_visible'] = self.use_visible
export_settings['gltf_renderable'] = self.use_renderable
export_settings['gltf_active_collection'] = self.use_active_collection
- # export_settings['gltf_selected'] = self.use_selection This can be uncomment when removing compatibility of export_selected
+ export_settings['gltf_selected'] = self.use_selection
export_settings['gltf_layers'] = True # self.export_layers
export_settings['gltf_extras'] = self.export_extras
export_settings['gltf_yup'] = self.export_yup
@@ -1171,6 +1151,20 @@ class ImportGLTF2(Operator, ImportHelper):
self.loglevel = logging.NOTSET
+class GLTF_AddonPreferences(bpy.types.AddonPreferences):
+ bl_idname = __package__
+
+ settings_node_ui : bpy.props.BoolProperty(
+ default= False,
+ description="Displays glTF Settings node in Shader Editor (Menu Add > Ouput)"
+ )
+
+
+ def draw(self, context):
+ layout = self.layout
+ row = layout.row()
+ row.prop(self, "settings_node_ui", text="Shader Editor Add-ons")
+
def menu_func_import(self, context):
self.layout.operator(ImportGLTF2.bl_idname, text='glTF 2.0 (.glb/.gltf)')
@@ -1188,21 +1182,26 @@ classes = (
GLTF_PT_export_animation_skinning,
GLTF_PT_export_user_extensions,
ImportGLTF2,
- GLTF_PT_import_user_extensions
+ GLTF_PT_import_user_extensions,
+ GLTF_AddonPreferences
)
def register():
+ import io_scene_gltf2.blender.com.gltf2_blender_ui as blender_ui
for c in classes:
bpy.utils.register_class(c)
# bpy.utils.register_module(__name__)
+ blender_ui.register()
+
# add to the export / import menu
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
def unregister():
+ import io_scene_gltf2.blender.com.gltf2_blender_ui as blender_ui
for c in classes:
bpy.utils.unregister_class(c)
for f in exporter_extension_panel_unregister_functors:
@@ -1213,6 +1212,8 @@ def unregister():
f()
importer_extension_panel_unregister_functors.clear()
+ blender_ui.unregister()
+
# bpy.utils.unregister_module(__name__)
# remove from the export / import menu
diff --git a/io_scene_gltf2/blender/com/gltf2_blender_material_helpers.py b/io_scene_gltf2/blender/com/gltf2_blender_material_helpers.py
index f3d7122e..7b90b0a3 100755
--- a/io_scene_gltf2/blender/com/gltf2_blender_material_helpers.py
+++ b/io_scene_gltf2/blender/com/gltf2_blender_material_helpers.py
@@ -1,6 +1,15 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2018-2021 The glTF-Blender-IO authors.
+import bpy
def get_gltf_node_name():
return "glTF Settings"
+
+def create_settings_group(name):
+ gltf_node_group = bpy.data.node_groups.new(name, 'ShaderNodeTree')
+ gltf_node_group.inputs.new("NodeSocketFloat", "Occlusion")
+ gltf_node_group.nodes.new('NodeGroupOutput')
+ gltf_node_group_input = gltf_node_group.nodes.new('NodeGroupInput')
+ gltf_node_group_input.location = -200, 0
+ return gltf_node_group \ No newline at end of file
diff --git a/io_scene_gltf2/blender/com/gltf2_blender_ui.py b/io_scene_gltf2/blender/com/gltf2_blender_ui.py
new file mode 100644
index 00000000..59c364fb
--- /dev/null
+++ b/io_scene_gltf2/blender/com/gltf2_blender_ui.py
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2018-2022 The glTF-Blender-IO authors.
+
+import bpy
+from ..com.gltf2_blender_material_helpers import get_gltf_node_name, create_settings_group
+
+def create_gltf_ao_group(operator, group_name):
+
+ # create a new group
+ gltf_ao_group = bpy.data.node_groups.new(group_name, "ShaderNodeTree")
+
+ return gltf_ao_group
+
+class NODE_OT_GLTF_SETTINGS(bpy.types.Operator):
+ bl_idname = "node.gltf_settings_node_operator"
+ bl_label = "glTF Settings"
+
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ return space.type == "NODE_EDITOR" \
+ and context.object and context.object.active_material \
+ and context.object.active_material.use_nodes is True \
+ and bpy.context.preferences.addons['io_scene_gltf2'].preferences.settings_node_ui is True
+
+ def execute(self, context):
+ gltf_settings_node_name = get_gltf_node_name()
+ if gltf_settings_node_name in bpy.data.node_groups:
+ my_group = bpy.data.node_groups[get_gltf_node_name()]
+ else:
+ my_group = create_settings_group(gltf_settings_node_name)
+ node_tree = context.object.active_material.node_tree
+ new_node = node_tree.nodes.new("ShaderNodeGroup")
+ new_node.node_tree = bpy.data.node_groups[my_group.name]
+ return {"FINISHED"}
+
+
+def add_gltf_settings_to_menu(self, context) :
+ if bpy.context.preferences.addons['io_scene_gltf2'].preferences.settings_node_ui is True:
+ self.layout.operator("node.gltf_settings_node_operator")
+
+
+def register():
+ bpy.utils.register_class(NODE_OT_GLTF_SETTINGS)
+ bpy.types.NODE_MT_category_SH_NEW_OUTPUT.append(add_gltf_settings_to_menu)
+
+def unregister():
+ bpy.utils.unregister_class(NODE_OT_GLTF_SETTINGS)
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_export.py b/io_scene_gltf2/blender/exp/gltf2_blender_export.py
index ddcad91d..539c6b74 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_export.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_export.py
@@ -65,6 +65,8 @@ def __export(export_settings):
def __gather_gltf(exporter, export_settings):
active_scene_idx, scenes, animations = gltf2_blender_gather.gather_gltf2(export_settings)
+ unused_skins = export_settings['vtree'].get_unused_skins()
+
if export_settings['gltf_draco_mesh_compression']:
gltf2_io_draco_compression_extension.encode_scene_primitives(scenes, export_settings)
exporter.add_draco_extension()
@@ -75,6 +77,7 @@ def __gather_gltf(exporter, export_settings):
exporter.add_scene(scene, idx==active_scene_idx)
for animation in animations:
exporter.add_animation(animation)
+ exporter.traverse_unused_skins(unused_skins)
def __create_buffer(exporter, export_settings):
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py
index 04129996..402e06fa 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2018-2021 The glTF-Blender-IO authors.
+from copy import deepcopy
import bpy
from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached, cached_by_key
@@ -17,14 +18,17 @@ from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extension
from io_scene_gltf2.io.com.gltf2_io_debug import print_console
@cached
-def get_material_cache_key(blender_material, export_settings):
+def get_material_cache_key(blender_material, active_uvmap_index, export_settings):
# Use id of material
# Do not use bpy.types that can be unhashable
# Do not use material name, that can be not unique (when linked)
- return ((id(blender_material),))
+ return (
+ (id(blender_material),),
+ (active_uvmap_index,)
+ )
@cached_by_key(key=get_material_cache_key)
-def gather_material(blender_material, export_settings):
+def gather_material(blender_material, active_uvmap_index, export_settings):
"""
Gather the material used by the blender primitive.
@@ -35,26 +39,79 @@ def gather_material(blender_material, export_settings):
if not __filter_material(blender_material, export_settings):
return None
- mat_unlit = __gather_material_unlit(blender_material, export_settings)
+ mat_unlit = __gather_material_unlit(blender_material, active_uvmap_index, export_settings)
if mat_unlit is not None:
return mat_unlit
orm_texture = __gather_orm_texture(blender_material, export_settings)
- material = gltf2_io.Material(
+ emissive_texture, uvmap_actives_emissive_texture = __gather_emissive_texture(blender_material, export_settings)
+ extensions, uvmap_actives_extensions = __gather_extensions(blender_material, export_settings)
+ normal_texture, uvmap_actives_normal_texture = __gather_normal_texture(blender_material, export_settings)
+ occlusion_texture, uvmap_actives_occlusion_texture = __gather_occlusion_texture(blender_material, orm_texture, export_settings)
+ pbr_metallic_roughness, uvmap_actives_pbr_metallic_roughness = __gather_pbr_metallic_roughness(blender_material, orm_texture, export_settings)
+
+ base_material = gltf2_io.Material(
alpha_cutoff=__gather_alpha_cutoff(blender_material, export_settings),
alpha_mode=__gather_alpha_mode(blender_material, export_settings),
double_sided=__gather_double_sided(blender_material, export_settings),
emissive_factor=__gather_emissive_factor(blender_material, export_settings),
- emissive_texture=__gather_emissive_texture(blender_material, export_settings),
- extensions=__gather_extensions(blender_material, export_settings),
+ emissive_texture=emissive_texture,
+ extensions=extensions,
extras=__gather_extras(blender_material, export_settings),
name=__gather_name(blender_material, export_settings),
- normal_texture=__gather_normal_texture(blender_material, export_settings),
- occlusion_texture=__gather_occlusion_texture(blender_material, orm_texture, export_settings),
- pbr_metallic_roughness=__gather_pbr_metallic_roughness(blender_material, orm_texture, export_settings)
+ normal_texture=normal_texture,
+ occlusion_texture=occlusion_texture,
+ pbr_metallic_roughness=pbr_metallic_roughness
)
+
+ # merge all uvmap_actives
+ uvmap_actives = []
+ if uvmap_actives_emissive_texture:
+ uvmap_actives.extend(uvmap_actives_emissive_texture)
+ if uvmap_actives_extensions:
+ uvmap_actives.extend(uvmap_actives_extensions)
+ if uvmap_actives_normal_texture:
+ uvmap_actives.extend(uvmap_actives_normal_texture)
+ if uvmap_actives_occlusion_texture:
+ uvmap_actives.extend(uvmap_actives_occlusion_texture)
+ if uvmap_actives_pbr_metallic_roughness:
+ uvmap_actives.extend(uvmap_actives_pbr_metallic_roughness)
+
+ # Because some part of material are shared (eg pbr_metallic_roughness), we must copy the material
+ # Texture must be shared, but not TextureInfo
+ material = deepcopy(base_material)
+ __get_new_material_texture_shared(base_material, material)
+
+ active_uvmap_index = active_uvmap_index if active_uvmap_index != 0 else None
+
+ for tex in uvmap_actives:
+ if tex == "emissiveTexture":
+ material.emissive_texture.tex_coord = active_uvmap_index
+ elif tex == "normalTexture":
+ material.normal_texture.tex_coord = active_uvmap_index
+ elif tex == "occlusionTexture":
+ material.occlusion_texture.tex_coord = active_uvmap_index
+ elif tex == "baseColorTexture":
+ material.pbr_metallic_roughness.base_color_texture.tex_coord = active_uvmap_index
+ elif tex == "metallicRoughnessTexture":
+ material.pbr_metallic_roughness.metallic_roughness_texture.tex_coord = active_uvmap_index
+ elif tex == "clearcoatTexture":
+ material.extensions["KHR_materials_clearcoat"].extension['clearcoatTexture'].tex_coord = active_uvmap_index
+ elif tex == "clearcoatRoughnessTexture":
+ material.extensions["KHR_materials_clearcoat"].extension['clearcoatRoughnessTexture'].tex_coord = active_uvmap_index
+ elif tex == "clearcoatNormalTexture": #TODO not tested yet
+ material.extensions["KHR_materials_clearcoat"].extension['clearcoatNormalTexture'].tex_coord = active_uvmap_index
+ elif tex == "transmissionTexture": #TODO not tested yet
+ material.extensions["KHR_materials_transmission"].extension['transmissionTexture'].tex_coord = active_uvmap_index
+
+ # If material is not using active UVMap, we need to return the same material,
+ # Even if multiples meshes are using different active UVMap
+ if len(uvmap_actives) == 0 and active_uvmap_index != -1:
+ material = gather_material(blender_material, -1, export_settings)
+
+
# If emissive is set, from an emissive node (not PBR)
# We need to set manually default values for
# pbr_metallic_roughness.baseColor
@@ -80,6 +137,25 @@ def gather_material(blender_material, export_settings):
# 'material'] + ' not found. Please assign glTF 2.0 material or enable Blinn-Phong material in export.')
+def __get_new_material_texture_shared(base, node):
+ if node is None:
+ return
+ if callable(node) is True:
+ return
+ if node.__str__().startswith('__'):
+ return
+ if type(node) in [gltf2_io.TextureInfo, gltf2_io.MaterialOcclusionTextureInfoClass, gltf2_io.MaterialNormalTextureInfoClass]:
+ node.index = base.index
+ else:
+ if hasattr(node, '__dict__'):
+ for attr, value in node.__dict__.items():
+ __get_new_material_texture_shared(getattr(base, attr), value)
+ else:
+ # For extensions (on a dict)
+ if type(node).__name__ == 'dict':
+ for i in node.keys():
+ __get_new_material_texture_shared(base[i], node[i])
+
def __filter_material(blender_material, export_settings):
return export_settings[gltf2_blender_export_keys.MATERIALS]
@@ -155,17 +231,20 @@ def __gather_emissive_texture(blender_material, export_settings):
emissive = gltf2_blender_get.get_socket(blender_material, "Emissive")
if emissive is None:
emissive = gltf2_blender_get.get_socket_old(blender_material, "Emissive")
- return gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), export_settings)
+ emissive_texture, use_actives_uvmap_emissive = gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), export_settings)
+ return emissive_texture, ["emissiveTexture"] if use_actives_uvmap_emissive else None
def __gather_extensions(blender_material, export_settings):
extensions = {}
# KHR_materials_clearcoat
+ actives_uvmaps = []
- clearcoat_extension = __gather_clearcoat_extension(blender_material, export_settings)
+ clearcoat_extension, use_actives_uvmap_clearcoat = __gather_clearcoat_extension(blender_material, export_settings)
if clearcoat_extension:
extensions["KHR_materials_clearcoat"] = clearcoat_extension
+ actives_uvmaps.extend(use_actives_uvmap_clearcoat)
# KHR_materials_transmission
@@ -173,7 +252,7 @@ def __gather_extensions(blender_material, export_settings):
if transmission_extension:
extensions["KHR_materials_transmission"] = transmission_extension
- return extensions if extensions else None
+ return extensions, actives_uvmaps if extensions else None
def __gather_extras(blender_material, export_settings):
@@ -190,10 +269,11 @@ def __gather_normal_texture(blender_material, export_settings):
normal = gltf2_blender_get.get_socket(blender_material, "Normal")
if normal is None:
normal = gltf2_blender_get.get_socket_old(blender_material, "Normal")
- return gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
+ normal_texture, use_active_uvmap_normal = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
normal,
(normal,),
export_settings)
+ return normal_texture, ["normalTexture"] if use_active_uvmap_normal else None
def __gather_orm_texture(blender_material, export_settings):
@@ -231,7 +311,7 @@ def __gather_orm_texture(blender_material, export_settings):
return None
# Double-check this will past the filter in texture_info
- info = gltf2_blender_gather_texture_info.gather_texture_info(result[0], result, export_settings)
+ info, info_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(result[0], result, export_settings)
if info is None:
return None
@@ -241,10 +321,11 @@ def __gather_occlusion_texture(blender_material, orm_texture, export_settings):
occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion")
if occlusion is None:
occlusion = gltf2_blender_get.get_socket_old(blender_material, "Occlusion")
- return gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class(
+ occlusion_texture, use_active_uvmap_occlusion = gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class(
occlusion,
orm_texture or (occlusion,),
export_settings)
+ return occlusion_texture, ["occlusionTexture"] if use_active_uvmap_occlusion else None
def __gather_pbr_metallic_roughness(blender_material, orm_texture, export_settings):
@@ -284,7 +365,7 @@ def __gather_clearcoat_extension(blender_material, export_settings):
clearcoat_enabled = True
if not clearcoat_enabled:
- return None
+ return None, None
if isinstance(clearcoat_roughness_socket, bpy.types.NodeSocket) and not clearcoat_roughness_socket.is_linked:
clearcoat_extension['clearcoatRoughnessFactor'] = clearcoat_roughness_socket.default_value
@@ -302,28 +383,38 @@ def __gather_clearcoat_extension(blender_material, export_settings):
elif has_clearcoat_roughness_texture:
clearcoat_roughness_slots = (clearcoat_roughness_socket,)
+ use_actives_uvmaps = []
+
if len(clearcoat_roughness_slots) > 0:
if has_clearcoat_texture:
- clearcoat_extension['clearcoatTexture'] = gltf2_blender_gather_texture_info.gather_texture_info(
+ clearcoat_texture, clearcoat_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_socket,
clearcoat_roughness_slots,
export_settings,
)
+ clearcoat_extension['clearcoatTexture'] = clearcoat_texture
+ if clearcoat_texture_use_active_uvmap:
+ use_actives_uvmaps.append("clearcoatTexture")
if has_clearcoat_roughness_texture:
- clearcoat_extension['clearcoatRoughnessTexture'] = gltf2_blender_gather_texture_info.gather_texture_info(
+ clearcoat_roughness_texture, clearcoat_roughness_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_roughness_socket,
clearcoat_roughness_slots,
export_settings,
)
-
+ clearcoat_extension['clearcoatRoughnessTexture'] = clearcoat_roughness_texture
+ if clearcoat_roughness_texture_use_active_uvmap:
+ use_actives_uvmaps.append("clearcoatRoughnessTexture")
if __has_image_node_from_socket(clearcoat_normal_socket):
- clearcoat_extension['clearcoatNormalTexture'] = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
+ clearcoat_normal_texture, clearcoat_normal_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
clearcoat_normal_socket,
(clearcoat_normal_socket,),
export_settings
)
+ clearcoat_extension['clearcoatNormalTexture'] = clearcoat_normal_texture
+ if clearcoat_normal_texture_use_active_uvmap:
+ use_actives_uvmaps.append("clearcoatNormalTexture")
- return Extension('KHR_materials_clearcoat', clearcoat_extension, False)
+ return Extension('KHR_materials_clearcoat', clearcoat_extension, False), use_actives_uvmaps
def __gather_transmission_extension(blender_material, export_settings):
transmission_enabled = False
@@ -350,7 +441,7 @@ def __gather_transmission_extension(blender_material, export_settings):
transmission_slots = (transmission_socket,)
if len(transmission_slots) > 0:
- combined_texture = gltf2_blender_gather_texture_info.gather_texture_info(
+ combined_texture, use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
transmission_socket,
transmission_slots,
export_settings,
@@ -358,17 +449,19 @@ def __gather_transmission_extension(blender_material, export_settings):
if has_transmission_texture:
transmission_extension['transmissionTexture'] = combined_texture
- return Extension('KHR_materials_transmission', transmission_extension, False)
+ return Extension('KHR_materials_transmission', transmission_extension, False), ["transmissionTexture"] if use_active_uvmap else []
-def __gather_material_unlit(blender_material, export_settings):
+def __gather_material_unlit(blender_material, active_uvmap_index, export_settings):
gltf2_unlit = gltf2_blender_gather_materials_unlit
info = gltf2_unlit.detect_shadeless_material(blender_material, export_settings)
if info is None:
return None
- material = gltf2_io.Material(
+ base_color_texture, use_active_uvmap = gltf2_unlit.gather_base_color_texture(info, export_settings)
+
+ base_material = gltf2_io.Material(
alpha_cutoff=__gather_alpha_cutoff(blender_material, export_settings),
alpha_mode=__gather_alpha_mode(blender_material, export_settings),
double_sided=__gather_double_sided(blender_material, export_settings),
@@ -382,7 +475,7 @@ def __gather_material_unlit(blender_material, export_settings):
pbr_metallic_roughness=gltf2_io.MaterialPBRMetallicRoughness(
base_color_factor=gltf2_unlit.gather_base_color_factor(info, export_settings),
- base_color_texture=gltf2_unlit.gather_base_color_texture(info, export_settings),
+ base_color_texture=base_color_texture,
metallic_factor=0.0,
roughness_factor=0.9,
metallic_roughness_texture=None,
@@ -391,6 +484,19 @@ def __gather_material_unlit(blender_material, export_settings):
)
)
+ if use_active_uvmap is not None:
+ # Because some part of material are shared (eg pbr_metallic_roughness), we must copy the material
+ # Texture must be shared, but not TextureInfo
+ material = deepcopy(base_material)
+ __get_new_material_texture_shared(base_material, material)
+ material.pbr_metallic_roughness.base_color_texture.tex_coord = active_uvmap_index
+ elif use_active_uvmap is None and active_uvmap_index != -1:
+ # If material is not using active UVMap, we need to return the same material,
+ # Even if multiples meshes are using different active UVMap
+ material = gather_material(blender_material, -1, export_settings)
+ else:
+ material = base_material
+
export_user_extensions('gather_material_unlit_hook', export_settings, material, blender_material)
return material
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py
index 9395aa43..0b40ffd6 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py
@@ -13,21 +13,31 @@ from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extension
@cached
def gather_material_pbr_metallic_roughness(blender_material, orm_texture, export_settings):
if not __filter_pbr_material(blender_material, export_settings):
- return None
+ return None, None
+
+ base_color_texture, use_active_uvmap_base_color_texture = __gather_base_color_texture(blender_material, export_settings)
+ metallic_roughness_texture, use_active_uvmap_metallic_roughness_texture = __gather_metallic_roughness_texture(blender_material, orm_texture, export_settings)
material = gltf2_io.MaterialPBRMetallicRoughness(
base_color_factor=__gather_base_color_factor(blender_material, export_settings),
- base_color_texture=__gather_base_color_texture(blender_material, export_settings),
+ base_color_texture=base_color_texture,
extensions=__gather_extensions(blender_material, export_settings),
extras=__gather_extras(blender_material, export_settings),
metallic_factor=__gather_metallic_factor(blender_material, export_settings),
- metallic_roughness_texture=__gather_metallic_roughness_texture(blender_material, orm_texture, export_settings),
+ metallic_roughness_texture=metallic_roughness_texture,
roughness_factor=__gather_roughness_factor(blender_material, export_settings)
)
+ # merge all use_active_uvmap infos
+ uvmap_actives = []
+ if use_active_uvmap_base_color_texture is True:
+ uvmap_actives.append("baseColorTexture")
+ if use_active_uvmap_metallic_roughness_texture is True:
+ uvmap_actives.append("metallicRoughnessTexture")
+
export_user_extensions('gather_material_pbr_metallic_roughness_hook', export_settings, material, blender_material, orm_texture)
- return material
+ return material, uvmap_actives
def __filter_pbr_material(blender_material, export_settings):
@@ -82,7 +92,7 @@ def __gather_base_color_texture(blender_material, export_settings):
if socket is not None and __has_image_node_from_socket(socket)
)
if not inputs:
- return None
+ return None, None
return gltf2_blender_gather_texture_info.gather_texture_info(inputs[0], inputs, export_settings)
@@ -118,7 +128,7 @@ def __gather_metallic_roughness_texture(blender_material, orm_texture, export_se
if not hasMetal and not hasRough:
metallic_roughness = gltf2_blender_get.get_socket_old(blender_material, "MetallicRoughness")
if metallic_roughness is None or not __has_image_node_from_socket(metallic_roughness):
- return None
+ return None, None
texture_input = (metallic_roughness,)
elif not hasMetal:
texture_input = (roughness_socket,)
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_unlit.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_unlit.py
index 2645f1f7..e104b7f1 100644
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_unlit.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_unlit.py
@@ -127,9 +127,10 @@ def gather_base_color_texture(info, export_settings):
# because gather_image determines how to pack images based on the
# names of sockets, and the names are hard-coded to a Principled
# style graph.
- return gltf2_blender_gather_texture_info.gather_texture_info(
+ unlit_texture, unlit_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
sockets[0],
sockets,
export_settings,
)
- return None
+ return unlit_texture, ["unlitTexture"] if unlit_use_active_uvmap else None
+ return None, None
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
index 9e5ce648..367c30f5 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives.py
@@ -57,6 +57,13 @@ def gather_primitives(
"""
primitives = []
+ # retrieve active render UVMap
+ active_uvmap_idx = 0
+ for i in range(len(blender_mesh.uv_layers)):
+ if blender_mesh.uv_layers[i].active_render is True:
+ active_uvmap_idx = i
+ break
+
blender_primitives = __gather_cache_primitives(blender_mesh, uuid_for_skined_data,
vertex_groups, modifiers, export_settings)
@@ -73,7 +80,8 @@ def gather_primitives(
if mat is not None:
material = gltf2_blender_gather_materials.gather_material(
mat,
- export_settings,
+ active_uvmap_idx,
+ export_settings
)
primitive = gltf2_io.MeshPrimitive(
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_texture_info.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_texture_info.py
index 2618973b..15b101ad 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_texture_info.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_texture_info.py
@@ -36,15 +36,15 @@ def __gather_texture_info_helper(
kind: str,
export_settings):
if not __filter_texture_info(primary_socket, blender_shader_sockets, export_settings):
- return None
+ return None, None
- tex_transform, tex_coord = __gather_texture_transform_and_tex_coord(primary_socket, export_settings)
+ tex_transform, tex_coord, use_active_uvmap = __gather_texture_transform_and_tex_coord(primary_socket, export_settings)
fields = {
'extensions': __gather_extensions(tex_transform, export_settings),
'extras': __gather_extras(blender_shader_sockets, export_settings),
'index': __gather_index(blender_shader_sockets, export_settings),
- 'tex_coord': tex_coord,
+ 'tex_coord': tex_coord
}
if kind == 'DEFAULT':
@@ -59,11 +59,11 @@ def __gather_texture_info_helper(
texture_info = gltf2_io.MaterialOcclusionTextureInfoClass(**fields)
if texture_info.index is None:
- return None
+ return None, None
export_user_extensions('gather_texture_info_hook', export_settings, texture_info, blender_shader_sockets)
- return texture_info
+ return texture_info, use_active_uvmap
def __filter_texture_info(primary_socket, blender_shader_sockets, export_settings):
@@ -151,15 +151,17 @@ def __gather_texture_transform_and_tex_coord(primary_socket, export_settings):
node = previous_node(node.inputs['Vector'])
texcoord_idx = 0
+ use_active_uvmap = True
if node and node.type == 'UVMAP' and node.uv_map:
# Try to gather map index.
for blender_mesh in bpy.data.meshes:
i = blender_mesh.uv_layers.find(node.uv_map)
if i >= 0:
texcoord_idx = i
+ use_active_uvmap = False
break
- return texture_transform, texcoord_idx or None
+ return texture_transform, texcoord_idx or None, use_active_uvmap
def __get_tex_from_socket(socket):
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
index d3edd50a..643cbea0 100644
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
@@ -5,6 +5,7 @@ import bpy
import uuid
from . import gltf2_blender_export_keys
+from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions
from mathutils import Quaternion, Matrix
class VExportNode:
@@ -255,6 +256,7 @@ class VExportTree:
def filter(self):
self.filter_tag()
+ export_user_extensions('gather_tree_filter_tag_hook', self.export_settings, self)
self.filter_perform()
@@ -372,3 +374,12 @@ class VExportTree:
if len(candidates) > 0:
n.armature = candidates[0].uuid
del n.armature_needed
+
+ def get_unused_skins(self):
+ from .gltf2_blender_gather_skins import gather_skin
+ skins = []
+ for n in [n for n in self.nodes.values() if n.blender_type == VExportNode.ARMATURE]:
+ if len([m for m in self.nodes.values() if m.keep_tag is True and m.blender_type == VExportNode.OBJECT and m.armature == n.uuid]) == 0:
+ skin = gather_skin(n.uuid, self.export_settings)
+ skins.append(skin)
+ return skins
diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py b/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py
index 9761e81c..574693d7 100755
--- a/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py
+++ b/io_scene_gltf2/blender/exp/gltf2_blender_gltf2_exporter.py
@@ -174,6 +174,10 @@ class GlTF2Exporter:
if active:
self.__gltf.scene = scene_num
+ def traverse_unused_skins(self, skins):
+ for s in skins:
+ self.__traverse(s)
+
def add_animation(self, animation: gltf2_io.Animation):
"""
Add an animation to the glTF.
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py
index 1780998c..a5d10a7a 100755
--- a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py
+++ b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py
@@ -3,7 +3,7 @@
import bpy
from ...io.com.gltf2_io import TextureInfo, MaterialPBRMetallicRoughness
-from ..com.gltf2_blender_material_helpers import get_gltf_node_name
+from ..com.gltf2_blender_material_helpers import get_gltf_node_name, create_settings_group
from .gltf2_blender_texture import texture
from .gltf2_blender_KHR_materials_clearcoat import \
clearcoat, clearcoat_roughness, clearcoat_normal
@@ -552,16 +552,11 @@ def make_settings_node(mh):
node.node_tree = get_settings_group()
return node
-
def get_settings_group():
gltf_node_group_name = get_gltf_node_name()
if gltf_node_group_name in bpy.data.node_groups:
gltf_node_group = bpy.data.node_groups[gltf_node_group_name]
else:
# Create a new node group
- gltf_node_group = bpy.data.node_groups.new(gltf_node_group_name, 'ShaderNodeTree')
- gltf_node_group.inputs.new("NodeSocketFloat", "Occlusion")
- gltf_node_group.nodes.new('NodeGroupOutput')
- gltf_node_group_input = gltf_node_group.nodes.new('NodeGroupInput')
- gltf_node_group_input.location = -200, 0
+ gltf_node_group = create_settings_group(gltf_node_group_name)
return gltf_node_group
diff --git a/io_scene_gltf2/io/exp/gltf2_io_export.py b/io_scene_gltf2/io/exp/gltf2_io_export.py
index 49cc4a78..aee74ba9 100755
--- a/io_scene_gltf2/io/exp/gltf2_io_export.py
+++ b/io_scene_gltf2/io/exp/gltf2_io_export.py
@@ -7,6 +7,7 @@
import json
import struct
+from io_scene_gltf2.io.exp.gltf2_io_user_extensions import export_user_extensions
#
# Globals
@@ -19,13 +20,18 @@ from collections import OrderedDict
def save_gltf(gltf, export_settings, encoder, glb_buffer):
- indent = None
- separators = (',', ':')
+ # Use a class here, to be able to pass data by reference to hook (to be able to change them inside hook)
+ class GlTF_format:
+ def __init__(self, indent, separators):
+ self.indent = indent
+ self.separators = separators
+
+ gltf_format = GlTF_format(None, (',', ':'))
if export_settings['gltf_format'] != 'GLB':
- indent = 4
+ gltf_format.indent = 4
# The comma is typically followed by a newline, so no trailing whitespace is needed on it.
- separators = (',', ' : ')
+ gltf_format.separators = (',', ' : ')
sort_order = [
"asset",
@@ -48,8 +54,11 @@ def save_gltf(gltf, export_settings, encoder, glb_buffer):
"samplers",
"buffers"
]
+
+ export_user_extensions('gather_gltf_encoded_hook', export_settings, gltf_format, sort_order)
+
gltf_ordered = OrderedDict(sorted(gltf.items(), key=lambda item: sort_order.index(item[0])))
- gltf_encoded = json.dumps(gltf_ordered, indent=indent, separators=separators, cls=encoder, allow_nan=False)
+ gltf_encoded = json.dumps(gltf_ordered, indent=gltf_format.indent, separators=gltf_format.separators, cls=encoder, allow_nan=False)
#
diff --git a/viewport_vr_preview/operators.py b/viewport_vr_preview/operators.py
index 6d45c500..29938b8b 100644
--- a/viewport_vr_preview/operators.py
+++ b/viewport_vr_preview/operators.py
@@ -193,7 +193,7 @@ class VIEW3D_OT_add_camera_from_vr_landmark(Operator):
scene.collection.objects.link(new_cam)
angle = lm.base_pose_angle
new_cam.location = lm.base_pose_location
- new_cam.rotation_euler = (math.pi, 0, angle)
+ new_cam.rotation_euler = (math.pi / 2, 0, angle)
return {'FINISHED'}