Skip to content

Commit 1ccb1fd

Browse files
authored
Merge pull request #275 from AsoboStudio/glTF-Blender-IO-MSFS-v1.3.2
glTF blender io msfs v1.3.2
2 parents 2eea85b + 6956781 commit 1ccb1fd

File tree

8 files changed

+83
-98
lines changed

8 files changed

+83
-98
lines changed

addons/io_scene_gltf2_msfs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"author": "Luca Pierabella, Yasmine Khodja, Wing42, pepperoni505, ronh991, and others",
2525
"description": "This toolkit prepares your 3D assets to be used for Microsoft Flight Simulator",
2626
"blender": (3, 3, 0),
27-
"version": (1, 3, 1),
27+
"version": (1, 3, 2),
2828
"location": "File > Import-Export",
2929
"category": "Import-Export",
3030
"tracker_url": "https://github.com/AsoboStudio/glTF-Blender-IO-MSFS"

addons/io_scene_gltf2_msfs/blender/material/utils/msfs_material_enum.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class MSFS_ShaderNodes(Enum):
101101
emissiveMulScale = "Emissive Multiplier Scale"
102102
RGBCurves = "RGB Curves"
103103
emissiveMul = "Emissive Multiplier"
104+
normalScale = "Normal Scale"
104105
normalMapSampler = "Normal Map Sampler"
105106
detailColorTex = "Detail Color(RGBA)"
106107
detailCompTex = "Detail Occlusion(R) Roughness(G) Metallic(B)"
@@ -114,7 +115,7 @@ class MSFS_ShaderNodes(Enum):
114115
combineUVScale = "Combine UV Scale"
115116
combineUVOffset = "Combine UV Offset"
116117
mulUVScale = "Multiply UV Scale"
117-
addUVOffset = "Multiply UV Offset"
118+
addUVOffset = "Add UV Offset"
118119
detailNormalMapSampler = "Detail Normal Map Sampler"
119120
blendNormalMap = "Blend Normal Map"
120121
blendColorMap = "Blend Color Map"

addons/io_scene_gltf2_msfs/blender/msfs_material_function.py

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def defaultShadersTree(self):
163163
)
164164

165165
## Comp Texture
166-
# Out[0] : Blend Comp Occlusion Metalic Roughness -> In[1]
166+
# Out[0] : Blend Comp Occlusion Metallic Roughness -> In[1]
167167
compTexNode = self.addNode(
168168
name = MSFS_ShaderNodes.compTex.value,
169169
typeNode = MSFS_ShaderNodesTypes.shaderNodeTexImage.value,
@@ -508,20 +508,6 @@ def defaultShadersTree(self):
508508
## Links
509509
self.link(splitOccMetalRoughNode.inputs[0], blendCompMapNode.outputs[0])
510510

511-
## Occlusion Multiplier
512-
# In[1] : Split Occ Metal Rough -> Out[0]
513-
occlusionMulNode = self.addNode(
514-
name = MSFS_ShaderNodes.occlusionMul.value,
515-
typeNode = MSFS_ShaderNodesTypes.shaderNodeMath.value,
516-
operation = "MULTIPLY",
517-
location = (500.0, 200.0),
518-
width = 200.0,
519-
frame = omrFrame
520-
)
521-
occlusionMulNode.inputs[0].default_value = 1.0
522-
## Links
523-
self.link(occlusionMulNode.inputs[1], splitOccMetalRoughNode.outputs[0])
524-
525511
## Roughness Multiplier
526512
# In[1] : Split Occ Metal Rough -> Out[1]
527513
roughnessMulNode = self.addNode(
@@ -601,12 +587,24 @@ def defaultShadersTree(self):
601587
color = (0.5, 0.25, 0.25)
602588
)
603589

590+
## Normal scale
591+
# Out[0] : Normap Map Sampler -> In[0]
592+
normalScaleNode = self.addNode(
593+
name = MSFS_ShaderNodes.normalScale.value,
594+
typeNode = MSFS_ShaderNodesTypes.shaderNodeValue.value,
595+
location = (-300.0, -350.0),
596+
frame = normalFrame
597+
)
598+
599+
normalScaleNode.outputs[0].default_value = 1.0
600+
604601
# Fix the normal view by reversing the green channel
605602
# since blender can only render openGL normal textures
606603
RGBCurvesNode = self.addNode(
607604
name = MSFS_ShaderNodes.RGBCurves.value,
608605
typeNode = MSFS_ShaderNodesTypes.shaderNodeRGBCurve.value,
609-
location = (-300.0, -400.0)
606+
location = (-300.0, -400.0),
607+
frame = normalFrame
610608
)
611609
curveMapping = RGBCurvesNode.mapping.curves[1]
612610
curveMapping.points[0].location = (0.0, 1.0)
@@ -623,6 +621,7 @@ def defaultShadersTree(self):
623621
)
624622

625623
# Links
624+
self.link(normalMapSamplerNode.inputs[0], normalScaleNode.outputs[0])
626625
self.link(normalMapSamplerNode.inputs[1], normalTexNode.outputs[0])
627626

628627
## Detail Normal Map Sampler
@@ -754,8 +753,8 @@ def setEmissiveColor(self, color):
754753
self.updateEmissiveLinks()
755754

756755
def setNormalScale(self, scale):
757-
nodeNormalMapSampler = self.getNodeByName(MSFS_ShaderNodes.normalMapSampler.value)
758-
nodeNormalMapSampler.inputs[0].default_value = scale
756+
nodeNormalScale = self.getNodeByName(MSFS_ShaderNodes.normalScale.value)
757+
nodeNormalScale.outputs[0].default_value = scale
759758
self.updateNormalLinks()
760759

761760
def setDetailNormalTex(self, tex):
@@ -845,7 +844,7 @@ def updateNormalLinks(self):
845844
nodeDetailNormalScale = self.getNodeByName(MSFS_ShaderNodes.detailNormalScale.value)
846845
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)
847846

848-
# normal
847+
# Normal
849848
self.link(nodeNormalTex.outputs[0], nodeRGBCurves.inputs[1])
850849
self.link(nodeRGBCurves.outputs[0], nodeNormalMapSampler.inputs[1])
851850
self.link(nodeNormalMapSampler.outputs[0], nodeBlendNormalMap.inputs[1])
@@ -855,10 +854,8 @@ def updateNormalLinks(self):
855854

856855
if nodeNormalTex.image and not nodeDetailNormalTex.image:
857856
self.link(nodeNormalMapSampler.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.normal.value])
858-
859857
elif nodeNormalTex.image and nodeDetailNormalTex.image:
860858
self.link(nodeBlendNormalMap.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.normal.value])
861-
862859
else:
863860
self.unLinkNodeInput(nodePrincipledBSDF, MSFS_PrincipledBSDFInputs.normal.value)
864861

@@ -867,7 +864,6 @@ def updateEmissiveLinks(self):
867864
nodeEmissiveScale = self.getNodeByName(MSFS_ShaderNodes.emissiveScale.value)
868865
nodeEmissiveColor = self.getNodeByName(MSFS_ShaderNodes.emissiveColor.value)
869866
nodeMulEmissive = self.getNodeByName(MSFS_ShaderNodes.emissiveMul.value)
870-
# nodeMulEmissiveScale = self.getNodeByName(MSFS_ShaderNodes.emissiveMulScale.value)
871867
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)
872868

873869
# emissive
@@ -889,7 +885,6 @@ def updateCompLinks(self):
889885
nodeSeparateComp = self.getNodeByName(MSFS_ShaderNodes.compSeparate.value)
890886
nodeMulMetallic = self.getNodeByName(MSFS_ShaderNodes.metallicMul.value)
891887
nodeMulRoughness = self.getNodeByName(MSFS_ShaderNodes.roughnessMul.value)
892-
nodeMulOcclusion = self.getNodeByName(MSFS_ShaderNodes.occlusionMul.value)
893888
nodeGltfSettings = self.getNodeByName(MSFS_ShaderNodes.glTFSettings.value)
894889
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)
895890

@@ -902,30 +897,25 @@ def updateCompLinks(self):
902897
self.link(nodeBlendCompMap.outputs[0], nodeSeparateComp.inputs[0])
903898
self.link(nodeMetallicScale.outputs[0], nodeMulMetallic.inputs[0])
904899
self.link(nodeRoughnessScale.outputs[0], nodeMulRoughness.inputs[0])
905-
self.link(nodeSeparateComp.outputs[0], nodeMulOcclusion.inputs[1])
906900
self.link(nodeSeparateComp.outputs[1], nodeMulRoughness.inputs[1])
907901
self.link(nodeSeparateComp.outputs[2], nodeMulMetallic.inputs[1])
908902

909903
if not nodeCompTex.image and not nodeDetailCompTex.image:
910904
self.link(nodeRoughnessScale.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
911905
self.link(nodeMetallicScale.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.metallic.value])
912906

913-
elif nodeCompTex.image and not nodeDetailCompTex.image:
914-
nodeBlendCompMap.blend_type = "ADD"
915-
self.link(nodeRoughnessScale.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
907+
self.unLinkNodeInput(nodeGltfSettings, 0)
908+
else: # nodeCompTex.image or nodeDetailCompTex.image (if we have both images or only one of them)
909+
self.link(nodeSeparateComp.outputs[0], nodeGltfSettings.inputs[0])
910+
self.link(nodeMulRoughness.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
916911
self.link(nodeMulMetallic.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.metallic.value])
917912

918-
elif not nodeCompTex.image and nodeDetailCompTex.image:
919-
nodeBlendCompMap.blend_type = "ADD"
920-
self.link(nodeMulRoughness.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
921-
self.link(nodeMetallicScale.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.metallic.value])
913+
if nodeCompTex.image and nodeDetailCompTex.image:
914+
nodeBlendCompMap.blend_type = "MULTIPLY"
915+
else: # we have only one of the two images
916+
nodeBlendCompMap.blend_type = "ADD"
922917

923-
else:
924-
nodeBlendCompMap.blend_type = "MULTIPLY"
925-
self.link(nodeMulRoughness.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
926-
self.link(nodeMulMetallic.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.metallic.value])
927918

928-
self.link(nodeMulOcclusion.outputs[0], nodeGltfSettings.inputs[0])
929919

930920
def setBlendMode(self, blendMode):
931921
if blendMode == "BLEND":

addons/io_scene_gltf2_msfs/blender/msfs_material_prop_update.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,12 @@ def update_msfs_material_type(self, context):
135135
@staticmethod
136136
def reset_material_prop_object(self):
137137
self.msfs_alpha_cutoff = 0.5
138-
self.msfs_ao_use_uv2 = False
139138
self.msfs_base_color_blend_factor = 1.0
140139
self.msfs_base_color_factor = [0.8, 0.8, 0.8, 1.0]
141140
self.msfs_base_color_texture = None
142141
self.msfs_blend_mask_texture = None
143142
self.msfs_clamp_uv_x = False
144143
self.msfs_clamp_uv_y = False
145-
self.msfs_clamp_uv_z = False
146144
self.msfs_collision_material = False
147145
self.msfs_day_night_cycle = False
148146
self.msfs_detail_blend_threshold = 0.1
@@ -169,7 +167,7 @@ def reset_material_prop_object(self):
169167
self.msfs_glass_deformation_factor = 0.0
170168
self.msfs_glass_reflection_mask_factor = 0.0
171169
self.msfs_metallic_blend_factor = 0.0
172-
self.msfs_metallic_factor = 0.0
170+
self.msfs_metallic_factor = 1.0
173171
self.msfs_no_cast_shadow = False
174172
self.msfs_normal_blend_factor = 1.0
175173
self.msfs_normal_scale = 1.0
@@ -189,7 +187,7 @@ def reset_material_prop_object(self):
189187
self.msfs_responsive_aa = False
190188
self.msfs_road_collision_material = False
191189
self.msfs_roughness_blend_factor = 1.0
192-
self.msfs_roughness_factor = 0.5
190+
self.msfs_roughness_factor = 1.0
193191
self.msfs_sss_color = [0.8, 0.8, 0.8, 1.0]
194192
self.msfs_use_pearl = False
195193
self.msfs_uv_offset_u = 0.0

addons/io_scene_gltf2_msfs/com/msfs_material_props.py

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class AsoboMaterialCommon:
2222
class Defaults:
2323
BaseColorFactor = [0.8, 0.8, 0.8, 1.0]
2424
EmissiveFactor = [0.0, 0.0, 0.0]
25-
MetallicFactor = 0.0
26-
RoughnessFactor = 0.5
25+
MetallicFactor = 1.0
26+
RoughnessFactor = 1.0
2727
NormalScale = 1.0
2828
EmissiveScale = 1.0
2929
AlphaMode = "OPAQUE"
@@ -287,6 +287,10 @@ def from_dict(
287287
@staticmethod
288288
def to_extension(blender_material, gltf2_material, export_settings):
289289
# All the properties here (besides some textures, which we handle elsewhere) are exported from the Khronos exporter
290+
gltf2_material.emissive_factor = [f * blender_material.msfs_emissive_scale for f in blender_material.msfs_emissive_factor]
291+
292+
if "KHR_materials_emissive_strength" in gltf2_material.extensions:
293+
gltf2_material.extensions.pop("KHR_materials_emissive_strength")
290294
pass
291295

292296

@@ -759,21 +763,14 @@ class AsoboMaterialUVOptions:
759763
SerializedName = "ASOBO_material_UV_options"
760764

761765
class Defaults:
762-
AOUseUV2 = False
763766
clampUVX = False
764767
clampUVY = False
765-
clampUVZ = False
766768
UVOffsetU = 0.0
767769
UVOffsetV = 0.0
768770
UVTilingU = 1.0
769771
UVTilingV = 1.0
770772
UVRotation = 0.0
771773

772-
bpy.types.Material.msfs_ao_use_uv2 = bpy.props.BoolProperty(
773-
name="AO Use UV2",
774-
default=Defaults.AOUseUV2,
775-
options=set(),
776-
)
777774

778775
bpy.types.Material.msfs_clamp_uv_x = bpy.props.BoolProperty(
779776
name="Clamp UV U",
@@ -787,12 +784,6 @@ class Defaults:
787784
options=set(),
788785
)
789786

790-
bpy.types.Material.msfs_clamp_uv_z = bpy.props.BoolProperty( # Doesn't seem to actually be used, which makes sense. Keeping just in case
791-
name="Clamp UV Z",
792-
default=Defaults.clampUVZ,
793-
options=set(),
794-
)
795-
796787
bpy.types.Material.msfs_uv_offset_u = bpy.props.FloatProperty(
797788
name="UV Offset U",
798789
min=-10.0,
@@ -844,13 +835,11 @@ def from_dict(blender_material, gltf2_material, import_settings):
844835
if extension is None:
845836
return
846837

847-
if extension.get("AOUseUV2"):
848-
blender_material.msfs_ao_use_uv2 = extension.get("AOUseUV2")
849838
if extension.get("clampUVX"):
850839
blender_material.msfs_clamp_uv_x = extension.get("clampUVX")
851840
if extension.get("clampUVY"):
852841
blender_material.msfs_clamp_uv_y = extension.get("clampUVY")
853-
if extension.get("clampUVZ"):
842+
if extension.get("clampUVZ"): # Deprecated
854843
blender_material.msfs_clamp_uv_z = extension.get("clampUVZ")
855844
if extension.get("UVOffsetU"):
856845
blender_material.msfs_uv_offset_u = extension.get("UVOffsetU")
@@ -867,10 +856,8 @@ def from_dict(blender_material, gltf2_material, import_settings):
867856
def to_extension(blender_material, gltf2_material, export_settings):
868857
result = {}
869858
if (
870-
(blender_material.msfs_ao_use_uv2
871-
or blender_material.msfs_clamp_uv_x
859+
(blender_material.msfs_clamp_uv_x
872860
or blender_material.msfs_clamp_uv_y
873-
or blender_material.msfs_clamp_uv_z
874861
or (
875862
blender_material.msfs_uv_offset_u != AsoboMaterialUVOptions.Defaults.UVOffsetU
876863
or blender_material.msfs_uv_offset_v != AsoboMaterialUVOptions.Defaults.UVOffsetV
@@ -883,10 +870,8 @@ def to_extension(blender_material, gltf2_material, export_settings):
883870
and blender_material.msfs_material_type != "msfs_invisible"
884871
and blender_material.msfs_material_type != "msfs_environment_occluder"
885872
):
886-
result["AOUseUV2"] = blender_material.msfs_ao_use_uv2
887873
result["clampUVX"] = blender_material.msfs_clamp_uv_x
888874
result["clampUVY"] = blender_material.msfs_clamp_uv_y
889-
result["clampUVZ"] = blender_material.msfs_clamp_uv_z
890875
result["UVOffsetU"] = blender_material.msfs_uv_offset_u
891876
result["UVOffsetV"] = blender_material.msfs_uv_offset_v
892877
result["UVTilingU"] = blender_material.msfs_uv_tiling_u

addons/io_scene_gltf2_msfs/io/msfs_multi_export.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ def export(file_path):
6969
export_frame_step=settings.export_frame_step,
7070
export_force_sampling=settings.export_force_sampling,
7171
export_nla_strips=settings.export_nla_strips,
72-
export_nla_strips_merged_animation_name=settings.export_nla_strips_merged_animation_name,
7372
export_def_bones=settings.export_def_bones,
7473
export_current_frame=settings.export_current_frame,
7574
export_skins=settings.export_skins,
@@ -214,7 +213,7 @@ def select_recursive(obj):
214213
for obj in lod.collection.all_objects:
215214
obj.select_set(True)
216215
else:
217-
select_recursive(lod.object)
216+
select_recursive(lod.objectLOD)
218217

219218
if lod_group.folder_name != "":
220219
exportPath = bpy.path.ensure_ext(os.path.join(bpy.path.abspath(lod_group.folder_name), os.path.splitext(lod.file_name)[0]), ".gltf")

addons/io_scene_gltf2_msfs/io/msfs_multi_export_objects.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
class MultiExporterLOD(bpy.types.PropertyGroup):
23-
object: bpy.props.PointerProperty(name="", type=bpy.types.Object)
23+
objectLOD: bpy.props.PointerProperty(name="", type=bpy.types.Object)
2424
collection: bpy.props.PointerProperty(name="", type=bpy.types.Collection)
2525

2626
enabled: bpy.props.BoolProperty(name="", default=False)
@@ -58,8 +58,8 @@ def lod_is_visible(context, lod):
5858
return False
5959
else:
6060
if (
61-
(not context.scene.multi_exporter_show_hidden_objects and lod.object.hide_get()) or
62-
(lod.object is None or lod.object not in list(bpy.context.window.view_layer.objects))
61+
(not context.scene.multi_exporter_show_hidden_objects and lod.objectLOD.hide_get()) or
62+
(lod.objectLOD is None or lod.objectLOD not in list(bpy.context.window.view_layer.objects))
6363
):
6464
return False
6565

@@ -77,7 +77,7 @@ def update_grouped_by(self, context):
7777

7878
@staticmethod
7979
def get_group_from_name(name):
80-
matches = re.findall("^(?i)x[0-9]_|_lod[0-9]+", name)
80+
matches = re.findall("^x[0-9]_|_LOD[0-9]+", name)
8181
# If an object starts with xN_ or ends with _LODN, treat as an LOD
8282
if matches:
8383
# Get base object group name from object
@@ -109,8 +109,8 @@ def reload_lod_groups(self, context):
109109
continue
110110
else:
111111
if (
112-
not lod.object in list(context.scene.objects)
113-
or not MSFS_OT_ReloadLODGroups.get_group_from_name(lod.object.name) == lod_group.group_name
112+
not lod.objectLOD in list(context.scene.objects)
113+
or not MSFS_OT_ReloadLODGroups.get_group_from_name(lod.objectLOD.name) == lod_group.group_name
114114
):
115115
lod_groups[i].lods.remove(j)
116116
continue
@@ -151,9 +151,9 @@ def reload_lod_groups(self, context):
151151
lod.file_name = collection.name
152152
else:
153153
for obj in found_lod_groups[lod_group]:
154-
if obj not in [lod.object for lod in lod_groups[lod_group_index].lods]:
154+
if obj not in [lod.objectLOD for lod in lod_groups[lod_group_index].lods]:
155155
lod = lod_groups[lod_group_index].lods.add()
156-
lod.object = obj
156+
lod.objectLOD = obj
157157
lod.file_name = obj.name
158158

159159
def execute(self, context):
@@ -229,7 +229,7 @@ def draw(self, context):
229229
if sort_by_collection:
230230
row.prop(lod, "enabled", text=lod.collection.name)
231231
else:
232-
row.prop(lod, "enabled", text=lod.object.name)
232+
row.prop(lod, "enabled", text=lod.objectLOD.name)
233233
subrow = row.column()
234234
subrow.prop(lod, "lod_value", text="LOD Value")
235235
# subrow.prop(lod, "flatten_on_export", text="Flatten on Export") # Disable these two options for now as there's not a great way to implement them

0 commit comments

Comments
 (0)