Other/unsupported material option with stub rendertypes and UI elements + fill MaterialProperties on import

This commit is contained in:
William Herald Snyder 2022-01-15 11:45:38 -05:00
parent c314592d48
commit bae32bdfe4
7 changed files with 168 additions and 97 deletions

View File

@ -18,6 +18,29 @@ class Rendertype(Enum):
NORMALMAPPED_ENVMAPPED = 26 NORMALMAPPED_ENVMAPPED = 26
NORMALMAPPED = 27 NORMALMAPPED = 27
NORMALMAPPED_TILED_ENVMAP = 29 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): class MaterialFlags(Flag):
NONE = 0 NONE = 0

View File

@ -5,6 +5,8 @@ import bpy
from typing import Dict from typing import Dict
from .msh_material import * from .msh_material import *
from .msh_material_utilities import _RENDERTYPES_MAPPING
def gather_materials() -> Dict[str, Material]: def gather_materials() -> Dict[str, Material]:
""" Gathers the Blender materials and returns them as """ Gathers the Blender materials and returns them as
a dictionary of strings and Material objects. """ 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.rendertype = _read_material_props_rendertype(props)
result.flags = _read_material_props_flags(props) result.flags = _read_material_props_flags(props)
result.data = _read_material_props_data(props) result.data = _read_material_props_data(props)
result.texture0 = props.diffuse_map
result.texture1 = _read_normal_map_or_distortion_map_texture(props) if "UNSUPPORTED" not in props.rendertype:
result.texture2 = _read_detail_texture(props) result.texture0 = props.diffuse_map
result.texture3 = _read_envmap_texture(props) 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 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: 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: def _read_material_props_flags(props) -> MaterialFlags:
if "REFRACTION" in props.rendertype: if "REFRACTION" in props.rendertype:
@ -79,6 +81,8 @@ def _read_material_props_flags(props) -> MaterialFlags:
return flags return flags
def _read_material_props_data(props) -> Tuple[int, int]: 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: if "SCROLLING" in props.rendertype:
return (props.scroll_speed_u, props.scroll_speed_v) return (props.scroll_speed_u, props.scroll_speed_v)
if "BLINK" in props.rendertype: if "BLINK" in props.rendertype:

View File

@ -3,7 +3,11 @@
import bpy import bpy
from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatVectorProperty, IntProperty from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatVectorProperty, IntProperty
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from .msh_material import *
from .msh_material_ui_strings import * from .msh_material_ui_strings import *
from .msh_material_utilities import _REVERSE_RENDERTYPES_MAPPING
UI_MATERIAL_RENDERTYPES = ( UI_MATERIAL_RENDERTYPES = (
('NORMAL_BF2', "00 Normal (SWBF2)", UI_RENDERTYPE_NORMAL_BF2_DESC), ('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_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_ENVMAPPED_BF2', "26 Normalmapped Envmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_ENVMAPPED_BF2_DESC),
('NORMALMAPPED_BF2', "27 Normalmapped (SWBF2)", UI_RENDERTYPE_NORMALMAPPED_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): def _make_anim_length_entry(length):
from math import sqrt from math import sqrt
@ -182,6 +188,17 @@ class MaterialProperties(PropertyGroup):
"distort the scene behind them. Should be a normal map " "distort the scene behind them. Should be a normal map "
"with '-forceformat v8u8' in it's '.tga.option' file.") "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): class MaterialPropertiesPanel(bpy.types.Panel):
""" Creates a Panel in the Object properties window """ """ Creates a Panel in the Object properties window """
bl_label = "SWBF .msh Properties" bl_label = "SWBF .msh Properties"
@ -190,6 +207,8 @@ class MaterialPropertiesPanel(bpy.types.Panel):
bl_region_type = 'WINDOW' bl_region_type = 'WINDOW'
bl_context = "material" bl_context = "material"
def draw(self, context): def draw(self, context):
if context.material is None: if context.material is None:
return return
@ -199,6 +218,10 @@ class MaterialPropertiesPanel(bpy.types.Panel):
material_props = context.material.swbf_msh material_props = context.material.swbf_msh
layout.prop(material_props, "rendertype") layout.prop(material_props, "rendertype")
if "UNSUPPORTED" in material_props.rendertype:
layout.prop(material_props, "rendertype_value")
layout.prop(material_props, "specular_color") layout.prop(material_props, "specular_color")
if "REFRACTION" not in material_props.rendertype: if "REFRACTION" not in material_props.rendertype:
@ -233,21 +256,31 @@ class MaterialPropertiesPanel(bpy.types.Panel):
elif "NORMALMAPPED_TILED" in material_props.rendertype: elif "NORMALMAPPED_TILED" in material_props.rendertype:
row.prop(material_props, "normal_map_tiling_u") row.prop(material_props, "normal_map_tiling_u")
row.prop(material_props, "normal_map_tiling_v") 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: else:
row.prop(material_props, "detail_map_tiling_u") row.prop(material_props, "detail_map_tiling_u")
row.prop(material_props, "detail_map_tiling_v") row.prop(material_props, "detail_map_tiling_v")
layout.label(text="Texture Maps: ") 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: if "REFRACTION" not in material_props.rendertype:
layout.prop(material_props, "detail_map") layout.prop(material_props, "detail_map")
if "NORMALMAPPED" in material_props.rendertype: if "NORMALMAPPED" in material_props.rendertype:
layout.prop(material_props, "normal_map") layout.prop(material_props, "normal_map")
if "ENVMAPPED" in material_props.rendertype: if "ENVMAPPED" in material_props.rendertype:
layout.prop(material_props, "environment_map") 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")

View File

@ -6,6 +6,10 @@ from .msh_material import *
from .msh_material_gather import * from .msh_material_gather import *
from .msh_material_properties import * from .msh_material_properties import *
from .msh_material_utilities import _REVERSE_RENDERTYPES_MAPPING
from math import sqrt
import os import os
@ -36,35 +40,22 @@ def fill_material_props(material : Material, material_properties):
if material_properties is None or material is None: if material_properties is None or material is None:
return 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.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_rendertype(material, material_properties)
_fill_material_props_flags(material, material_properties) _fill_material_props_flags(material, material_properties)
_fill_material_props_data(material, material_properties) _fill_material_props_data(material, material_properties)
_fill_material_props_texture_maps(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)
def _fill_material_props_rendertype(material, material_properties): def _fill_material_props_rendertype(material, material_properties):
if material.rendertype in _REVERSE_RENDERTYPES_MAPPING:
_REVERSE_RENDERTYPES_MAPPING = { material_properties.rendertype = _REVERSE_RENDERTYPES_MAPPING[material.rendertype]
Rendertype.NORMAL : "NORMAL_BF2", else:
Rendertype.SCROLLING : "SCROLLING_BF2", material_properties.rendertype = "UNSUPPORTED"
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]
def _fill_material_props_flags(material, material_properties): 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): 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.data_value_0 = material.data[0]
material_properties.blink_min_brightness = material.data[0] material_properties.data_value_1 = material.data[1]
material_properties.blink_speed = material.data[1]
elif material.rendertype == Rendertype.NORMALMAPPED_TILED_ENVMAP or material.rendertype == Rendertype.NORMALMAPPED_TILED: material_properties.scroll_speed_u = material.data[0]
material_properties.normal_map_tiling_u = material.data[0] material_properties.scroll_speed_v = material.data[1]
material_properties.normal_map_tiling_v = material.data[1]
elif material.rendertype == Rendertype.REFRACTION: material_properties.blink_min_brightness = material.data[0]
pass material_properties.blink_speed = material.data[1]
elif material.rendertype == Rendertype.ANIMATED: material_properties.normal_map_tiling_u = material.data[0]
material_properties.normal_map_tiling_v = material.data[1]
anim_length_index = int(sqrt(length)) - 1 anim_length_index = int(sqrt(material.data[0]))
if animation_length_index < 0: if anim_length_index < 0:
animation_length_index = 0 anim_length_index = 0
elif animation_length_index > len(UI_MATERIAL_ANIMATION_LENGTHS): elif anim_length_index > len(UI_MATERIAL_ANIMATION_LENGTHS):
animation_length_index = len(UI_MATERIAL_ANIMATION_LENGTHS) - 1 anim_length_index = len(UI_MATERIAL_ANIMATION_LENGTHS) - 1
material_properties.animation_length = UI_MATERIAL_ANIMATION_LENGTHS[animation_length_index] material_properties.animation_length = UI_MATERIAL_ANIMATION_LENGTHS[anim_length_index][0]
material_properties.animation_speed = material.data[1] material_properties.animation_speed = material.data[1]
else: material_properties.detail_map_tiling_u = material.data[0]
material_properties.detail_map_tiling_u = material.data[0] material_properties.detail_map_tiling_v = material.data[1]
material_properties.detail_map_tiling_v = material.data[1]
def _fill_normal_map_or_distortion_map_texture(material, material_properties): def _fill_material_props_texture_maps(material, material_properties):
if material.rendertype == Rendertype.REFRACTION:
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 material_properties.distortion_map = material.texture1
elif material.rendertype.value > 24:
material_properties.normal_map = material.texture1 material_properties.normal_map = material.texture1
def _fill_detail_texture(material, material_properties):
if material.rendertype != Rendertype.REFRACTION:
material_properties.detail_map = material.texture2 material_properties.detail_map = material.texture2
def _fill_envmap_texture(material, material_properties):
if material.rendertype != Rendertype.ENVMAPPED:
material_properties.environment_map = material.texture3 material_properties.environment_map = material.texture3

View File

@ -1,5 +1,10 @@
""" UI strings that are too long to have in msh_materials_properties.py """ """ 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 = \ UI_RENDERTYPE_DETAIL_MAP_DESC = \
"Can optionally have a Detail Map." "Can optionally have a Detail Map."

View File

@ -4,6 +4,35 @@ from typing import Dict, List
from .msh_material import * from .msh_material import *
from .msh_model 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], def remove_unused_materials(materials: Dict[str, Material],
models: List[Model]) -> Dict[str, Material]: models: List[Model]) -> Dict[str, Material]:
""" Given a dictionary of materials and a list of models """ Given a dictionary of materials and a list of models

View File

@ -211,11 +211,7 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model:
with modl.read_child() as mndx: with modl.read_child() as mndx:
index = mndx.read_u32() index = mndx.read_u32()
global model_counter 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 global mndx_remap
mndx_remap[index] = model_counter mndx_remap[index] = model_counter
@ -255,6 +251,10 @@ def _read_modl(modl: Reader, materials_list: List[Material]) -> Model:
num_indicies = envl.read_u32() num_indicies = envl.read_u32()
envelope += [envl.read_u32() for _ in range(num_indicies)] envelope += [envl.read_u32() for _ in range(num_indicies)]
elif next_header_geom == "CLTH":
with geom.read_child() as clth:
pass
else: else:
geom.skip_bytes(1) geom.skip_bytes(1)
@ -359,7 +359,8 @@ def _read_segm(segm: Reader, materials_list: List[Material]) -> GeometrySegment:
for _ in range(num_tris): for _ in range(num_tris):
geometry_seg.triangles.append(ndxt.read_u16(3)) 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": elif next_header == "STRP":
strips : List[List[int]] = [] strips : List[List[int]] = []
@ -474,13 +475,6 @@ def _read_anm2(anm2: Reader) -> Animation:
anim.bone_frames[bone_crc] = frames 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: else:
anm2.skip_bytes(1) anm2.skip_bytes(1)