Skip to content

Commit

Permalink
Merge pull request #275 from AsoboStudio/glTF-Blender-IO-MSFS-v1.3.2
Browse files Browse the repository at this point in the history
glTF blender io msfs v1.3.2
  • Loading branch information
y-khodja authored Sep 20, 2023
2 parents 2eea85b + 6956781 commit 1ccb1fd
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 98 deletions.
2 changes: 1 addition & 1 deletion addons/io_scene_gltf2_msfs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"author": "Luca Pierabella, Yasmine Khodja, Wing42, pepperoni505, ronh991, and others",
"description": "This toolkit prepares your 3D assets to be used for Microsoft Flight Simulator",
"blender": (3, 3, 0),
"version": (1, 3, 1),
"version": (1, 3, 2),
"location": "File > Import-Export",
"category": "Import-Export",
"tracker_url": "https://github.com/AsoboStudio/glTF-Blender-IO-MSFS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class MSFS_ShaderNodes(Enum):
emissiveMulScale = "Emissive Multiplier Scale"
RGBCurves = "RGB Curves"
emissiveMul = "Emissive Multiplier"
normalScale = "Normal Scale"
normalMapSampler = "Normal Map Sampler"
detailColorTex = "Detail Color(RGBA)"
detailCompTex = "Detail Occlusion(R) Roughness(G) Metallic(B)"
Expand All @@ -114,7 +115,7 @@ class MSFS_ShaderNodes(Enum):
combineUVScale = "Combine UV Scale"
combineUVOffset = "Combine UV Offset"
mulUVScale = "Multiply UV Scale"
addUVOffset = "Multiply UV Offset"
addUVOffset = "Add UV Offset"
detailNormalMapSampler = "Detail Normal Map Sampler"
blendNormalMap = "Blend Normal Map"
blendColorMap = "Blend Color Map"
Expand Down
62 changes: 26 additions & 36 deletions addons/io_scene_gltf2_msfs/blender/msfs_material_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def defaultShadersTree(self):
)

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

## Occlusion Multiplier
# In[1] : Split Occ Metal Rough -> Out[0]
occlusionMulNode = self.addNode(
name = MSFS_ShaderNodes.occlusionMul.value,
typeNode = MSFS_ShaderNodesTypes.shaderNodeMath.value,
operation = "MULTIPLY",
location = (500.0, 200.0),
width = 200.0,
frame = omrFrame
)
occlusionMulNode.inputs[0].default_value = 1.0
## Links
self.link(occlusionMulNode.inputs[1], splitOccMetalRoughNode.outputs[0])

## Roughness Multiplier
# In[1] : Split Occ Metal Rough -> Out[1]
roughnessMulNode = self.addNode(
Expand Down Expand Up @@ -601,12 +587,24 @@ def defaultShadersTree(self):
color = (0.5, 0.25, 0.25)
)

## Normal scale
# Out[0] : Normap Map Sampler -> In[0]
normalScaleNode = self.addNode(
name = MSFS_ShaderNodes.normalScale.value,
typeNode = MSFS_ShaderNodesTypes.shaderNodeValue.value,
location = (-300.0, -350.0),
frame = normalFrame
)

normalScaleNode.outputs[0].default_value = 1.0

# Fix the normal view by reversing the green channel
# since blender can only render openGL normal textures
RGBCurvesNode = self.addNode(
name = MSFS_ShaderNodes.RGBCurves.value,
typeNode = MSFS_ShaderNodesTypes.shaderNodeRGBCurve.value,
location = (-300.0, -400.0)
location = (-300.0, -400.0),
frame = normalFrame
)
curveMapping = RGBCurvesNode.mapping.curves[1]
curveMapping.points[0].location = (0.0, 1.0)
Expand All @@ -623,6 +621,7 @@ def defaultShadersTree(self):
)

# Links
self.link(normalMapSamplerNode.inputs[0], normalScaleNode.outputs[0])
self.link(normalMapSamplerNode.inputs[1], normalTexNode.outputs[0])

## Detail Normal Map Sampler
Expand Down Expand Up @@ -754,8 +753,8 @@ def setEmissiveColor(self, color):
self.updateEmissiveLinks()

def setNormalScale(self, scale):
nodeNormalMapSampler = self.getNodeByName(MSFS_ShaderNodes.normalMapSampler.value)
nodeNormalMapSampler.inputs[0].default_value = scale
nodeNormalScale = self.getNodeByName(MSFS_ShaderNodes.normalScale.value)
nodeNormalScale.outputs[0].default_value = scale
self.updateNormalLinks()

def setDetailNormalTex(self, tex):
Expand Down Expand Up @@ -845,7 +844,7 @@ def updateNormalLinks(self):
nodeDetailNormalScale = self.getNodeByName(MSFS_ShaderNodes.detailNormalScale.value)
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)

# normal
# Normal
self.link(nodeNormalTex.outputs[0], nodeRGBCurves.inputs[1])
self.link(nodeRGBCurves.outputs[0], nodeNormalMapSampler.inputs[1])
self.link(nodeNormalMapSampler.outputs[0], nodeBlendNormalMap.inputs[1])
Expand All @@ -855,10 +854,8 @@ def updateNormalLinks(self):

if nodeNormalTex.image and not nodeDetailNormalTex.image:
self.link(nodeNormalMapSampler.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.normal.value])

elif nodeNormalTex.image and nodeDetailNormalTex.image:
self.link(nodeBlendNormalMap.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.normal.value])

else:
self.unLinkNodeInput(nodePrincipledBSDF, MSFS_PrincipledBSDFInputs.normal.value)

Expand All @@ -867,7 +864,6 @@ def updateEmissiveLinks(self):
nodeEmissiveScale = self.getNodeByName(MSFS_ShaderNodes.emissiveScale.value)
nodeEmissiveColor = self.getNodeByName(MSFS_ShaderNodes.emissiveColor.value)
nodeMulEmissive = self.getNodeByName(MSFS_ShaderNodes.emissiveMul.value)
# nodeMulEmissiveScale = self.getNodeByName(MSFS_ShaderNodes.emissiveMulScale.value)
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)

# emissive
Expand All @@ -889,7 +885,6 @@ def updateCompLinks(self):
nodeSeparateComp = self.getNodeByName(MSFS_ShaderNodes.compSeparate.value)
nodeMulMetallic = self.getNodeByName(MSFS_ShaderNodes.metallicMul.value)
nodeMulRoughness = self.getNodeByName(MSFS_ShaderNodes.roughnessMul.value)
nodeMulOcclusion = self.getNodeByName(MSFS_ShaderNodes.occlusionMul.value)
nodeGltfSettings = self.getNodeByName(MSFS_ShaderNodes.glTFSettings.value)
nodePrincipledBSDF = self.getNodeByName(MSFS_ShaderNodes.principledBSDF.value)

Expand All @@ -902,30 +897,25 @@ def updateCompLinks(self):
self.link(nodeBlendCompMap.outputs[0], nodeSeparateComp.inputs[0])
self.link(nodeMetallicScale.outputs[0], nodeMulMetallic.inputs[0])
self.link(nodeRoughnessScale.outputs[0], nodeMulRoughness.inputs[0])
self.link(nodeSeparateComp.outputs[0], nodeMulOcclusion.inputs[1])
self.link(nodeSeparateComp.outputs[1], nodeMulRoughness.inputs[1])
self.link(nodeSeparateComp.outputs[2], nodeMulMetallic.inputs[1])

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

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

elif not nodeCompTex.image and nodeDetailCompTex.image:
nodeBlendCompMap.blend_type = "ADD"
self.link(nodeMulRoughness.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.roughness.value])
self.link(nodeMetallicScale.outputs[0], nodePrincipledBSDF.inputs[MSFS_PrincipledBSDFInputs.metallic.value])
if nodeCompTex.image and nodeDetailCompTex.image:
nodeBlendCompMap.blend_type = "MULTIPLY"
else: # we have only one of the two images
nodeBlendCompMap.blend_type = "ADD"

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

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

def setBlendMode(self, blendMode):
if blendMode == "BLEND":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,12 @@ def update_msfs_material_type(self, context):
@staticmethod
def reset_material_prop_object(self):
self.msfs_alpha_cutoff = 0.5
self.msfs_ao_use_uv2 = False
self.msfs_base_color_blend_factor = 1.0
self.msfs_base_color_factor = [0.8, 0.8, 0.8, 1.0]
self.msfs_base_color_texture = None
self.msfs_blend_mask_texture = None
self.msfs_clamp_uv_x = False
self.msfs_clamp_uv_y = False
self.msfs_clamp_uv_z = False
self.msfs_collision_material = False
self.msfs_day_night_cycle = False
self.msfs_detail_blend_threshold = 0.1
Expand All @@ -169,7 +167,7 @@ def reset_material_prop_object(self):
self.msfs_glass_deformation_factor = 0.0
self.msfs_glass_reflection_mask_factor = 0.0
self.msfs_metallic_blend_factor = 0.0
self.msfs_metallic_factor = 0.0
self.msfs_metallic_factor = 1.0
self.msfs_no_cast_shadow = False
self.msfs_normal_blend_factor = 1.0
self.msfs_normal_scale = 1.0
Expand All @@ -189,7 +187,7 @@ def reset_material_prop_object(self):
self.msfs_responsive_aa = False
self.msfs_road_collision_material = False
self.msfs_roughness_blend_factor = 1.0
self.msfs_roughness_factor = 0.5
self.msfs_roughness_factor = 1.0
self.msfs_sss_color = [0.8, 0.8, 0.8, 1.0]
self.msfs_use_pearl = False
self.msfs_uv_offset_u = 0.0
Expand Down
31 changes: 8 additions & 23 deletions addons/io_scene_gltf2_msfs/com/msfs_material_props.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class AsoboMaterialCommon:
class Defaults:
BaseColorFactor = [0.8, 0.8, 0.8, 1.0]
EmissiveFactor = [0.0, 0.0, 0.0]
MetallicFactor = 0.0
RoughnessFactor = 0.5
MetallicFactor = 1.0
RoughnessFactor = 1.0
NormalScale = 1.0
EmissiveScale = 1.0
AlphaMode = "OPAQUE"
Expand Down Expand Up @@ -287,6 +287,10 @@ def from_dict(
@staticmethod
def to_extension(blender_material, gltf2_material, export_settings):
# All the properties here (besides some textures, which we handle elsewhere) are exported from the Khronos exporter
gltf2_material.emissive_factor = [f * blender_material.msfs_emissive_scale for f in blender_material.msfs_emissive_factor]

if "KHR_materials_emissive_strength" in gltf2_material.extensions:
gltf2_material.extensions.pop("KHR_materials_emissive_strength")
pass


Expand Down Expand Up @@ -759,21 +763,14 @@ class AsoboMaterialUVOptions:
SerializedName = "ASOBO_material_UV_options"

class Defaults:
AOUseUV2 = False
clampUVX = False
clampUVY = False
clampUVZ = False
UVOffsetU = 0.0
UVOffsetV = 0.0
UVTilingU = 1.0
UVTilingV = 1.0
UVRotation = 0.0

bpy.types.Material.msfs_ao_use_uv2 = bpy.props.BoolProperty(
name="AO Use UV2",
default=Defaults.AOUseUV2,
options=set(),
)

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

bpy.types.Material.msfs_clamp_uv_z = bpy.props.BoolProperty( # Doesn't seem to actually be used, which makes sense. Keeping just in case
name="Clamp UV Z",
default=Defaults.clampUVZ,
options=set(),
)

bpy.types.Material.msfs_uv_offset_u = bpy.props.FloatProperty(
name="UV Offset U",
min=-10.0,
Expand Down Expand Up @@ -844,13 +835,11 @@ def from_dict(blender_material, gltf2_material, import_settings):
if extension is None:
return

if extension.get("AOUseUV2"):
blender_material.msfs_ao_use_uv2 = extension.get("AOUseUV2")
if extension.get("clampUVX"):
blender_material.msfs_clamp_uv_x = extension.get("clampUVX")
if extension.get("clampUVY"):
blender_material.msfs_clamp_uv_y = extension.get("clampUVY")
if extension.get("clampUVZ"):
if extension.get("clampUVZ"): # Deprecated
blender_material.msfs_clamp_uv_z = extension.get("clampUVZ")
if extension.get("UVOffsetU"):
blender_material.msfs_uv_offset_u = extension.get("UVOffsetU")
Expand All @@ -867,10 +856,8 @@ def from_dict(blender_material, gltf2_material, import_settings):
def to_extension(blender_material, gltf2_material, export_settings):
result = {}
if (
(blender_material.msfs_ao_use_uv2
or blender_material.msfs_clamp_uv_x
(blender_material.msfs_clamp_uv_x
or blender_material.msfs_clamp_uv_y
or blender_material.msfs_clamp_uv_z
or (
blender_material.msfs_uv_offset_u != AsoboMaterialUVOptions.Defaults.UVOffsetU
or blender_material.msfs_uv_offset_v != AsoboMaterialUVOptions.Defaults.UVOffsetV
Expand All @@ -883,10 +870,8 @@ def to_extension(blender_material, gltf2_material, export_settings):
and blender_material.msfs_material_type != "msfs_invisible"
and blender_material.msfs_material_type != "msfs_environment_occluder"
):
result["AOUseUV2"] = blender_material.msfs_ao_use_uv2
result["clampUVX"] = blender_material.msfs_clamp_uv_x
result["clampUVY"] = blender_material.msfs_clamp_uv_y
result["clampUVZ"] = blender_material.msfs_clamp_uv_z
result["UVOffsetU"] = blender_material.msfs_uv_offset_u
result["UVOffsetV"] = blender_material.msfs_uv_offset_v
result["UVTilingU"] = blender_material.msfs_uv_tiling_u
Expand Down
3 changes: 1 addition & 2 deletions addons/io_scene_gltf2_msfs/io/msfs_multi_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def export(file_path):
export_frame_step=settings.export_frame_step,
export_force_sampling=settings.export_force_sampling,
export_nla_strips=settings.export_nla_strips,
export_nla_strips_merged_animation_name=settings.export_nla_strips_merged_animation_name,
export_def_bones=settings.export_def_bones,
export_current_frame=settings.export_current_frame,
export_skins=settings.export_skins,
Expand Down Expand Up @@ -214,7 +213,7 @@ def select_recursive(obj):
for obj in lod.collection.all_objects:
obj.select_set(True)
else:
select_recursive(lod.object)
select_recursive(lod.objectLOD)

if lod_group.folder_name != "":
exportPath = bpy.path.ensure_ext(os.path.join(bpy.path.abspath(lod_group.folder_name), os.path.splitext(lod.file_name)[0]), ".gltf")
Expand Down
18 changes: 9 additions & 9 deletions addons/io_scene_gltf2_msfs/io/msfs_multi_export_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


class MultiExporterLOD(bpy.types.PropertyGroup):
object: bpy.props.PointerProperty(name="", type=bpy.types.Object)
objectLOD: bpy.props.PointerProperty(name="", type=bpy.types.Object)
collection: bpy.props.PointerProperty(name="", type=bpy.types.Collection)

enabled: bpy.props.BoolProperty(name="", default=False)
Expand Down Expand Up @@ -58,8 +58,8 @@ def lod_is_visible(context, lod):
return False
else:
if (
(not context.scene.multi_exporter_show_hidden_objects and lod.object.hide_get()) or
(lod.object is None or lod.object not in list(bpy.context.window.view_layer.objects))
(not context.scene.multi_exporter_show_hidden_objects and lod.objectLOD.hide_get()) or
(lod.objectLOD is None or lod.objectLOD not in list(bpy.context.window.view_layer.objects))
):
return False

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

@staticmethod
def get_group_from_name(name):
matches = re.findall("^(?i)x[0-9]_|_lod[0-9]+", name)
matches = re.findall("^x[0-9]_|_LOD[0-9]+", name)
# If an object starts with xN_ or ends with _LODN, treat as an LOD
if matches:
# Get base object group name from object
Expand Down Expand Up @@ -109,8 +109,8 @@ def reload_lod_groups(self, context):
continue
else:
if (
not lod.object in list(context.scene.objects)
or not MSFS_OT_ReloadLODGroups.get_group_from_name(lod.object.name) == lod_group.group_name
not lod.objectLOD in list(context.scene.objects)
or not MSFS_OT_ReloadLODGroups.get_group_from_name(lod.objectLOD.name) == lod_group.group_name
):
lod_groups[i].lods.remove(j)
continue
Expand Down Expand Up @@ -151,9 +151,9 @@ def reload_lod_groups(self, context):
lod.file_name = collection.name
else:
for obj in found_lod_groups[lod_group]:
if obj not in [lod.object for lod in lod_groups[lod_group_index].lods]:
if obj not in [lod.objectLOD for lod in lod_groups[lod_group_index].lods]:
lod = lod_groups[lod_group_index].lods.add()
lod.object = obj
lod.objectLOD = obj
lod.file_name = obj.name

def execute(self, context):
Expand Down Expand Up @@ -229,7 +229,7 @@ def draw(self, context):
if sort_by_collection:
row.prop(lod, "enabled", text=lod.collection.name)
else:
row.prop(lod, "enabled", text=lod.object.name)
row.prop(lod, "enabled", text=lod.objectLOD.name)
subrow = row.column()
subrow.prop(lod, "lod_value", text="LOD Value")
# 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
Expand Down
Loading

0 comments on commit 1ccb1fd

Please sign in to comment.