From bae32bdfe426f7566b206076d6c47a92edd7e688 Mon Sep 17 00:00:00 2001 From: William Herald Snyder Date: Sat, 15 Jan 2022 11:45:38 -0500 Subject: [PATCH] Other/unsupported material option with stub rendertypes and UI elements + fill MaterialProperties on import --- addons/io_scene_swbf_msh/msh_material.py | 23 +++++ .../io_scene_swbf_msh/msh_material_gather.py | 36 ++++--- .../msh_material_properties.py | 53 ++++++++-- .../msh_material_to_blend.py | 99 ++++++++----------- .../msh_material_ui_strings.py | 5 + .../msh_material_utilities.py | 29 ++++++ addons/io_scene_swbf_msh/msh_scene_read.py | 20 ++-- 7 files changed, 168 insertions(+), 97 deletions(-) diff --git a/addons/io_scene_swbf_msh/msh_material.py b/addons/io_scene_swbf_msh/msh_material.py index 560e3bb..6b66700 100644 --- a/addons/io_scene_swbf_msh/msh_material.py +++ b/addons/io_scene_swbf_msh/msh_material.py @@ -18,6 +18,29 @@ class Rendertype(Enum): NORMALMAPPED_ENVMAPPED = 26 NORMALMAPPED = 27 NORMALMAPPED_TILED_ENVMAP = 29 + OTHER_1 = 1 + OTHER_2 = 2 + OTHER_4 = 4 + OTHER_5 = 5 + OTHER_8 = 8 + OTHER_9 = 9 + OTHER_10 = 10 + OTHER_11 = 11 + OTHER_12 = 12 + OTHER_13 = 13 + OTHER_14 = 14 + OTHER_15 = 15 + OTHER_16 = 16 + OTHER_17 = 17 + OTHER_18 = 18 + OTHER_19 = 19 + OTHER_20 = 20 + OTHER_21 = 21 + OTHER_23 = 23 + OTHER_28 = 28 + OTHER_30 = 30 + OTHER_31 = 31 + class MaterialFlags(Flag): NONE = 0 diff --git a/addons/io_scene_swbf_msh/msh_material_gather.py b/addons/io_scene_swbf_msh/msh_material_gather.py index 4fa3f3d..7f058f6 100644 --- a/addons/io_scene_swbf_msh/msh_material_gather.py +++ b/addons/io_scene_swbf_msh/msh_material_gather.py @@ -5,6 +5,8 @@ import bpy from typing import Dict from .msh_material import * +from .msh_material_utilities import _RENDERTYPES_MAPPING + def gather_materials() -> Dict[str, Material]: """ Gathers the Blender materials and returns them as a dictionary of strings and Material objects. """ @@ -31,27 +33,27 @@ def read_material(blender_material: bpy.types.Material) -> Material: result.rendertype = _read_material_props_rendertype(props) result.flags = _read_material_props_flags(props) result.data = _read_material_props_data(props) - result.texture0 = props.diffuse_map - result.texture1 = _read_normal_map_or_distortion_map_texture(props) - result.texture2 = _read_detail_texture(props) - result.texture3 = _read_envmap_texture(props) + + if "UNSUPPORTED" not in props.rendertype: + result.texture0 = props.diffuse_map + result.texture1 = _read_normal_map_or_distortion_map_texture(props) + result.texture2 = _read_detail_texture(props) + result.texture3 = _read_envmap_texture(props) + + else: + result.texture0 = props.texture_0 + result.texture1 = props.texture_1 + result.texture2 = props.texture_2 + result.texture3 = props.texture_3 return result -_RENDERTYPES_MAPPING = { - "NORMAL_BF2": Rendertype.NORMAL, - "SCROLLING_BF2": Rendertype.SCROLLING, - "ENVMAPPED_BF2": Rendertype.ENVMAPPED, - "ANIMATED_BF2": Rendertype.ANIMATED, - "REFRACTION_BF2": Rendertype.REFRACTION, - "BLINK_BF2": Rendertype.BLINK, - "NORMALMAPPED_TILED_BF2": Rendertype.NORMALMAPPED_TILED, - "NORMALMAPPED_ENVMAPPED_BF2": Rendertype.NORMALMAPPED_ENVMAPPED, - "NORMALMAPPED_BF2": Rendertype.NORMALMAPPED, - "NORMALMAPPED_TILED_ENVMAPPED_BF2": Rendertype.NORMALMAPPED_TILED_ENVMAP} def _read_material_props_rendertype(props) -> Rendertype: - return _RENDERTYPES_MAPPING[props.rendertype] + if "UNSUPPORTED" in props.rendertype: + return Rendertype(props.rendertype_value) + else: + return _RENDERTYPES_MAPPING[props.rendertype] def _read_material_props_flags(props) -> MaterialFlags: if "REFRACTION" in props.rendertype: @@ -79,6 +81,8 @@ def _read_material_props_flags(props) -> MaterialFlags: return flags def _read_material_props_data(props) -> Tuple[int, int]: + if "UNSUPPORTED" in props.rendertype: + return (props.data_value_0, props.data_value_1) if "SCROLLING" in props.rendertype: return (props.scroll_speed_u, props.scroll_speed_v) if "BLINK" in props.rendertype: diff --git a/addons/io_scene_swbf_msh/msh_material_properties.py b/addons/io_scene_swbf_msh/msh_material_properties.py index 97c7313..cdca6c8 100644 --- a/addons/io_scene_swbf_msh/msh_material_properties.py +++ b/addons/io_scene_swbf_msh/msh_material_properties.py @@ -3,7 +3,11 @@ import bpy from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatVectorProperty, IntProperty from bpy.types import PropertyGroup + +from .msh_material import * from .msh_material_ui_strings import * +from .msh_material_utilities import _REVERSE_RENDERTYPES_MAPPING + UI_MATERIAL_RENDERTYPES = ( ('NORMAL_BF2', "00 Normal (SWBF2)", UI_RENDERTYPE_NORMAL_BF2_DESC), @@ -15,7 +19,9 @@ UI_MATERIAL_RENDERTYPES = ( ('NORMALMAPPED_TILED_BF2', "24 Normalmapped Tiled (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_TILED_BF2_DESC), ('NORMALMAPPED_ENVMAPPED_BF2', "26 Normalmapped Envmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_ENVMAPPED_BF2_DESC), ('NORMALMAPPED_BF2', "27 Normalmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_BF2_DESC), - ('NORMALMAPPED_TILED_ENVMAPPED_BF2', "29 Normalmapped Tiled Envmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_TILED_ENVMAPPED_BF2_DESC)) + ('NORMALMAPPED_TILED_ENVMAPPED_BF2', "29 Normalmapped Tiled Envmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_TILED_ENVMAPPED_BF2_DESC), + ('UNSUPPORTED', "Other (SWBF1/2)", UI_RENDERTYPE_UNSUPPORTED_BF2_DESC)) + def _make_anim_length_entry(length): from math import sqrt @@ -182,6 +188,17 @@ class MaterialProperties(PropertyGroup): "distort the scene behind them. Should be a normal map " "with '-forceformat v8u8' in it's '.tga.option' file.") + data_value_0: IntProperty(name="", description="First data value") + data_value_1: IntProperty(name="", description="Second data value") + + rendertype_value: IntProperty(name="Rendertype Value", description="Raw number value of rendertype.", min=0, max=31) + + texture_0: StringProperty(name="1", description="First texture slot") + texture_1: StringProperty(name="2", description="Second texture slot") + texture_2: StringProperty(name="3", description="Third texture slot") + texture_3: StringProperty(name="4", description="Fourth texture slot") + + class MaterialPropertiesPanel(bpy.types.Panel): """ Creates a Panel in the Object properties window """ bl_label = "SWBF .msh Properties" @@ -190,6 +207,8 @@ class MaterialPropertiesPanel(bpy.types.Panel): bl_region_type = 'WINDOW' bl_context = "material" + + def draw(self, context): if context.material is None: return @@ -199,6 +218,10 @@ class MaterialPropertiesPanel(bpy.types.Panel): material_props = context.material.swbf_msh layout.prop(material_props, "rendertype") + + if "UNSUPPORTED" in material_props.rendertype: + layout.prop(material_props, "rendertype_value") + layout.prop(material_props, "specular_color") if "REFRACTION" not in material_props.rendertype: @@ -233,21 +256,31 @@ class MaterialPropertiesPanel(bpy.types.Panel): elif "NORMALMAPPED_TILED" in material_props.rendertype: row.prop(material_props, "normal_map_tiling_u") row.prop(material_props, "normal_map_tiling_v") + elif "UNSUPPORTED" in material_props.rendertype: + row.prop(material_props, "data_value_0") + row.prop(material_props, "data_value_1") else: row.prop(material_props, "detail_map_tiling_u") row.prop(material_props, "detail_map_tiling_v") layout.label(text="Texture Maps: ") - layout.prop(material_props, "diffuse_map") + if "UNSUPPORTED" not in material_props.rendertype: + layout.prop(material_props, "diffuse_map") - if "REFRACTION" not in material_props.rendertype: - layout.prop(material_props, "detail_map") + if "REFRACTION" not in material_props.rendertype: + layout.prop(material_props, "detail_map") - if "NORMALMAPPED" in material_props.rendertype: - layout.prop(material_props, "normal_map") + if "NORMALMAPPED" in material_props.rendertype: + layout.prop(material_props, "normal_map") - if "ENVMAPPED" in material_props.rendertype: - layout.prop(material_props, "environment_map") + if "ENVMAPPED" in material_props.rendertype: + layout.prop(material_props, "environment_map") + + if "REFRACTION" in material_props.rendertype: + layout.prop(material_props, "distortion_map") + else: + layout.prop(material_props, "texture_0") + layout.prop(material_props, "texture_1") + layout.prop(material_props, "texture_2") + layout.prop(material_props, "texture_3") - if "REFRACTION" in material_props.rendertype: - layout.prop(material_props, "distortion_map") diff --git a/addons/io_scene_swbf_msh/msh_material_to_blend.py b/addons/io_scene_swbf_msh/msh_material_to_blend.py index a0ae612..3ec0367 100644 --- a/addons/io_scene_swbf_msh/msh_material_to_blend.py +++ b/addons/io_scene_swbf_msh/msh_material_to_blend.py @@ -6,6 +6,10 @@ from .msh_material import * from .msh_material_gather import * from .msh_material_properties import * +from .msh_material_utilities import _REVERSE_RENDERTYPES_MAPPING + +from math import sqrt + import os @@ -36,35 +40,22 @@ def fill_material_props(material : Material, material_properties): if material_properties is None or material is None: return + material_properties.rendertype_value = material.rendertype.value + material_properties.specular_color = (material.specular_color[0], material.specular_color[1], material.specular_color[2]) - material_properties.diffuse_map = material.texture0 _fill_material_props_rendertype(material, material_properties) _fill_material_props_flags(material, material_properties) _fill_material_props_data(material, material_properties) - - _fill_normal_map_or_distortion_map_texture(material, material_properties) - _fill_detail_texture(material, material_properties) - _fill_envmap_texture(material, material_properties) + _fill_material_props_texture_maps(material, material_properties) def _fill_material_props_rendertype(material, material_properties): - - _REVERSE_RENDERTYPES_MAPPING = { - Rendertype.NORMAL : "NORMAL_BF2", - Rendertype.SCROLLING : "SCROLLING_BF2", - Rendertype.ENVMAPPED : "ENVMAPPED_BF2", - Rendertype.ANIMATED : "ANIMATED_BF2", - Rendertype.REFRACTION : "REFRACTION_BF2", - Rendertype.BLINK : "BLINK_BF2", - Rendertype.NORMALMAPPED_TILED : "NORMALMAPPED_TILED_BF2", - Rendertype.NORMALMAPPED_ENVMAPPED : "NORMALMAPPED_ENVMAPPED_BF2", - Rendertype.NORMALMAPPED : "NORMALMAPPED_BF2", - Rendertype.NORMALMAPPED_TILED_ENVMAP : "NORMALMAPPED_TILED_ENVMAPPED_BF2"} - - material_properties.rendertype = _REVERSE_RENDERTYPES_MAPPING[material.rendertype] - + if material.rendertype in _REVERSE_RENDERTYPES_MAPPING: + material_properties.rendertype = _REVERSE_RENDERTYPES_MAPPING[material.rendertype] + else: + material_properties.rendertype = "UNSUPPORTED" def _fill_material_props_flags(material, material_properties): @@ -85,49 +76,41 @@ def _fill_material_props_flags(material, material_properties): def _fill_material_props_data(material, material_properties): - if material.rendertype == Rendertype.SCROLLING: - material_properties.scroll_speed_u = material.data[0] - material_properties.scroll_speed_v = material.data[1] - - elif material.rendertype == Rendertype.BLINK: - material_properties.blink_min_brightness = material.data[0] - material_properties.blink_speed = material.data[1] - - elif material.rendertype == Rendertype.NORMALMAPPED_TILED_ENVMAP or material.rendertype == Rendertype.NORMALMAPPED_TILED: - material_properties.normal_map_tiling_u = material.data[0] - material_properties.normal_map_tiling_v = material.data[1] - - elif material.rendertype == Rendertype.REFRACTION: - pass - - elif material.rendertype == Rendertype.ANIMATED: - anim_length_index = int(sqrt(length)) - 1 - if animation_length_index < 0: - animation_length_index = 0 - elif animation_length_index > len(UI_MATERIAL_ANIMATION_LENGTHS): - animation_length_index = len(UI_MATERIAL_ANIMATION_LENGTHS) - 1 + material_properties.data_value_0 = material.data[0] + material_properties.data_value_1 = material.data[1] - material_properties.animation_length = UI_MATERIAL_ANIMATION_LENGTHS[animation_length_index] - material_properties.animation_speed = material.data[1] - - else: - material_properties.detail_map_tiling_u = material.data[0] - material_properties.detail_map_tiling_v = material.data[1] + material_properties.scroll_speed_u = material.data[0] + material_properties.scroll_speed_v = material.data[1] + + material_properties.blink_min_brightness = material.data[0] + material_properties.blink_speed = material.data[1] + + material_properties.normal_map_tiling_u = material.data[0] + material_properties.normal_map_tiling_v = material.data[1] + + anim_length_index = int(sqrt(material.data[0])) + if anim_length_index < 0: + anim_length_index = 0 + elif anim_length_index > len(UI_MATERIAL_ANIMATION_LENGTHS): + anim_length_index = len(UI_MATERIAL_ANIMATION_LENGTHS) - 1 + + material_properties.animation_length = UI_MATERIAL_ANIMATION_LENGTHS[anim_length_index][0] + material_properties.animation_speed = material.data[1] + + material_properties.detail_map_tiling_u = material.data[0] + material_properties.detail_map_tiling_v = material.data[1] -def _fill_normal_map_or_distortion_map_texture(material, material_properties): - if material.rendertype == Rendertype.REFRACTION: +def _fill_material_props_texture_maps(material, material_properties): + + material_properties.texture_0 = material.texture0 + material_properties.texture_1 = material.texture1 + material_properties.texture_2 = material.texture2 + material_properties.texture_3 = material.texture3 + + material_properties.diffuse_map = material.texture0 material_properties.distortion_map = material.texture1 - elif material.rendertype.value > 24: material_properties.normal_map = material.texture1 - - -def _fill_detail_texture(material, material_properties): - if material.rendertype != Rendertype.REFRACTION: material_properties.detail_map = material.texture2 - - -def _fill_envmap_texture(material, material_properties): - if material.rendertype != Rendertype.ENVMAPPED: material_properties.environment_map = material.texture3 diff --git a/addons/io_scene_swbf_msh/msh_material_ui_strings.py b/addons/io_scene_swbf_msh/msh_material_ui_strings.py index 2dd115d..d4fba86 100644 --- a/addons/io_scene_swbf_msh/msh_material_ui_strings.py +++ b/addons/io_scene_swbf_msh/msh_material_ui_strings.py @@ -1,5 +1,10 @@ """ UI strings that are too long to have in msh_materials_properties.py """ + +UI_RENDERTYPE_UNSUPPORTED_BF2_DESC = \ + "Unsupported rendertype. The raw values of the material "\ + "are fully accessible, but their purpose is unknown. " + UI_RENDERTYPE_DETAIL_MAP_DESC = \ "Can optionally have a Detail Map." diff --git a/addons/io_scene_swbf_msh/msh_material_utilities.py b/addons/io_scene_swbf_msh/msh_material_utilities.py index f390324..1765032 100644 --- a/addons/io_scene_swbf_msh/msh_material_utilities.py +++ b/addons/io_scene_swbf_msh/msh_material_utilities.py @@ -4,6 +4,35 @@ from typing import Dict, List from .msh_material import * from .msh_model import * + +_RENDERTYPES_MAPPING = { + "NORMAL_BF2": Rendertype.NORMAL, + "SCROLLING_BF2": Rendertype.SCROLLING, + "ENVMAPPED_BF2": Rendertype.ENVMAPPED, + "ANIMATED_BF2": Rendertype.ANIMATED, + "REFRACTION_BF2": Rendertype.REFRACTION, + "BLINK_BF2": Rendertype.BLINK, + "NORMALMAPPED_TILED_BF2": Rendertype.NORMALMAPPED_TILED, + "NORMALMAPPED_ENVMAPPED_BF2": Rendertype.NORMALMAPPED_ENVMAPPED, + "NORMALMAPPED_BF2": Rendertype.NORMALMAPPED, + "NORMALMAPPED_TILED_ENVMAPPED_BF2": Rendertype.NORMALMAPPED_TILED_ENVMAP} + + +_REVERSE_RENDERTYPES_MAPPING = { + Rendertype.NORMAL : "NORMAL_BF2", + Rendertype.SCROLLING : "SCROLLING_BF2", + Rendertype.ENVMAPPED : "ENVMAPPED_BF2", + Rendertype.ANIMATED : "ANIMATED_BF2", + Rendertype.REFRACTION : "REFRACTION_BF2", + Rendertype.BLINK : "BLINK_BF2", + Rendertype.NORMALMAPPED_TILED : "NORMALMAPPED_TILED_BF2", + Rendertype.NORMALMAPPED_ENVMAPPED : "NORMALMAPPED_ENVMAPPED_BF2", + Rendertype.NORMALMAPPED : "NORMALMAPPED_BF2", + Rendertype.NORMALMAPPED_TILED_ENVMAP : "NORMALMAPPED_TILED_ENVMAPPED_BF2"} + + + + def remove_unused_materials(materials: Dict[str, Material], models: List[Model]) -> Dict[str, Material]: """ Given a dictionary of materials and a list of models diff --git a/addons/io_scene_swbf_msh/msh_scene_read.py b/addons/io_scene_swbf_msh/msh_scene_read.py index e537dcc..f05267d 100644 --- a/addons/io_scene_swbf_msh/msh_scene_read.py +++ b/addons/io_scene_swbf_msh/msh_scene_read.py @@ -169,7 +169,7 @@ def _read_matd(matd: Reader) -> Material: elif next_header == "ATRB": with matd.read_child() as atrb: - mat.flags = MaterialFlags(atrb.read_u8()) + mat.flags = MaterialFlags(atrb.read_u8()) mat.rendertype = Rendertype(atrb.read_u8()) mat.data = atrb.read_u8(2) @@ -211,11 +211,7 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model: with modl.read_child() as mndx: index = mndx.read_u32() - global model_counter - #print(mndx.indent + "MNDX doesn't match counter, expected: {} found: {}".format(model_counter, index)) - #print("Model counter: {} MNDX: {}".format(model_counter, index)) - global mndx_remap mndx_remap[index] = model_counter @@ -255,6 +251,10 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model: num_indicies = envl.read_u32() envelope += [envl.read_u32() for _ in range(num_indicies)] + elif next_header_geom == "CLTH": + with geom.read_child() as clth: + pass + else: geom.skip_bytes(1) @@ -359,7 +359,8 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment: for _ in range(num_tris): geometry_seg.triangles.append(ndxt.read_u16(3)) - # + + # There could be major issues with this, so far it hasn't failed but its inelegance irks me elif next_header == "STRP": strips : List[List[int]] = [] @@ -474,13 +475,6 @@ def _read_anm2(anm2: Reader) -> Animation: anim.bone_frames[bone_crc] = frames - - for bone_crc in sorted(bone_crcs): - - bone_frames = anim.bone_frames[bone_crc] - - loc_frames = bone_frames[0] - rot_frames = bone_frames[1] else: anm2.skip_bytes(1)