Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions fast64_internal/f3d/f3d_gbi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,8 @@ def __init__(
self.global_data: FGlobalData = FGlobalData()
self.texturesSavedLastExport: int = 0 # hacky

self.reference_to_extern: list[str] = []

def processTexRefNonCITextures(self, fMaterial: FMaterial, material: bpy.types.Material, index: int):
"""
For non CI textures that use a texture reference, process additional textures that will possibly be loaded here.
Expand Down Expand Up @@ -2849,6 +2851,16 @@ def save_textures(self, exportPath):
def freePalettes(self):
pass

def add_refs_externs(self, data: CData):
for ref in self.reference_to_extern:
extern = f"extern u64 {ref}[];\n"

if extern not in data.source:
data.source += extern

if len(self.reference_to_extern) > 0:
data.source += "\n"


class FTexRect(FModel):
def __init__(self, name, matWriteMethod):
Expand Down
31 changes: 19 additions & 12 deletions fast64_internal/f3d/f3d_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,17 +780,15 @@ def rendermode_presets_checks(material: "F3DMaterialProperty"):
no_flags_2 = rdp.rendermode_preset_cycle_2 in f3d.rendermodePresetsWithoutFlags
if no_flags_1 and no_flags_2:
raise PluginError(
"Invalid combination of rendermode presets.\n" "Neither of these presets sets the rendermode flags."
"Invalid combination of rendermode presets.\nNeither of these presets sets the rendermode flags."
)
elif not no_flags_1 and not no_flags_2:
raise PluginError(
"Invalid combination of rendermode presets.\n" "Both of these presets set the rendermode flags."
"Invalid combination of rendermode presets.\nBoth of these presets set the rendermode flags."
)
else:
if no_flags_1:
raise PluginError(
"Invalid rendermode preset in 1-cycle.\n" "This preset does not set the rendermode flags."
)
raise PluginError("Invalid rendermode preset in 1-cycle.\nThis preset does not set the rendermode flags.")


# UI Assumptions:
Expand Down Expand Up @@ -2986,6 +2984,10 @@ class TextureProperty(PropertyGroup):
min=1,
default=16,
)
extern_refs: bpy.props.BoolProperty(
name="Extern Texture Reference",
description="Adds externs to the exported source, useful if the texture or palette reference is a symbol.",
)

menu: bpy.props.BoolProperty()
tex_set: bpy.props.BoolProperty(
Expand Down Expand Up @@ -3146,13 +3148,19 @@ def ui_image(

prop_input.prop(textureProp, "use_tex_reference")
if textureProp.use_tex_reference:
flipbook = getattr(material.flipbookGroup, "flipbook" + texIndex)

if (len(textureProp.tex_reference) > 0 and not textureProp.tex_reference.lower().startswith("0x")) or (
not flipbook.enable and len(textureProp.pal_reference) > 0 and not textureProp.pal_reference.lower().startswith("0x")
):
prop_input.prop(textureProp, "extern_refs")

prop_split(prop_input, textureProp, "tex_reference", "Texture Reference")
prop_split(prop_input, textureProp, "tex_reference_size", "Texture Size")
if textureProp.tex_format[:2] == "CI":
flipbook = getattr(material.flipbookGroup, "flipbook" + texIndex)
if flipbook is None or not flipbook.enable:
prop_split(prop_input, textureProp, "pal_reference", "Palette Reference")
prop_split(prop_input, textureProp, "pal_reference_size", "Palette Size")

if textureProp.tex_format[:2] == "CI" and not flipbook.enable:
prop_split(prop_input, textureProp, "pal_reference", "Palette Reference")
prop_split(prop_input, textureProp, "pal_reference_size", "Palette Size")

else:
prop_input.template_ID(
Expand Down Expand Up @@ -3996,8 +4004,7 @@ def draw_rdp_world_defaults(layout: UILayout, scene: Scene):
col.label(text="Saved to Repo Settings file", icon="PROPERTIES")
multilineLabel(
col,
text="If a material setting is the same as the default setting\n"
"it won't be set, otherwise a revert will be added.",
text="If a material setting is the same as the default setting\nit won't be set, otherwise a revert will be added.",
)
if scene.gameEditorMode == "Homebrew":
multilineLabel(
Expand Down
46 changes: 29 additions & 17 deletions fast64_internal/f3d/f3d_texture_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def initWithFace(self, obj, face):
raise PluginError(
f"Large texture material {self.materialName} has a face that needs"
+ f" to cover texels {self.sl}-{self.sh} x {self.tl}-{self.th}"
+ f" ({self.sh-self.sl+1} x {self.th-self.tl+1} texels) "
+ f" ({self.sh - self.sl + 1} x {self.th - self.tl + 1} texels) "
+ f"in format {self.texFormat}, which can't fit in TMEM."
)
self.faces.append(face)
Expand Down Expand Up @@ -635,23 +635,34 @@ def __init__(
if self.ti0.useTex and self.ti1.useTex:
if self.ti0.isTexCI != self.ti1.isTexCI:
raise PluginError("N64 does not support CI + non-CI texture. Must be both CI or neither CI.")
if (
self.ti0.isTexRef
and self.ti1.isTexRef
and self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference
and self.ti0.texProp.tex_reference_size != self.ti1.texProp.tex_reference_size
):
raise PluginError("Two textures with the same reference must have the same size.")

def assert_size(is_pal: bool):
p_str = " palette " if is_pal else " "

is_ref_enabled = (
self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference
if is_pal
else self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference
)

data_1 = self.ti0.texProp.pal_reference_size if is_pal else self.ti0.texProp.tex_reference_size
size_1 = list(data_1) if not isinstance(data_1, int) else [data_1]

data_2 = self.ti1.texProp.pal_reference_size if is_pal else self.ti1.texProp.tex_reference_size
size_2 = list(data_2) if not isinstance(data_2, int) else [data_2]

is_same_size = size_1[0] == size_2[0] and size_1[0] == size_2[0]

if self.ti0.isTexRef and self.ti1.isTexRef and is_ref_enabled and not is_same_size:
raise PluginError(f"Two textures with the same{p_str}reference must have the same{p_str}size.")

assert_size(False)

if self.isCI:
if self.ti0.palFormat != self.ti1.palFormat:
raise PluginError("Both CI textures must use the same palette format (usually RGBA16).")
if (
self.ti0.isTexRef
and self.ti1.isTexRef
and self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference
and self.ti0.texProp.pal_reference_size != self.ti1.texProp.pal_reference_size
):
raise PluginError("Two textures with the same palette reference must have the same palette size.")

assert_size(True)

self.palFormat = self.ti0.palFormat if self.ti0.useTex else self.ti1.palFormat

Expand Down Expand Up @@ -803,17 +814,18 @@ def writeAll(
or ( # reference
self.ti0.isTexRef
and self.ti0.texProp.tex_reference == self.ti1.texProp.tex_reference
and self.ti0.texProp.tex_reference_size == self.ti1.texProp.tex_reference_size
and list(self.ti0.texProp.tex_reference_size) == list(self.ti1.texProp.tex_reference_size)
and ( # ci format reference
not self.isCI
or (
self.ti0.texProp.pal_reference == self.ti1.texProp.pal_reference
and self.ti0.texProp.pal_reference_size == self.ti1.texProp.pal_reference_size
and list(self.ti0.texProp.pal_reference_size) == list(self.ti1.texProp.pal_reference_size)
)
)
)
)
)

useLargeTextures = material.mat_ver > 3 and f3dMat.use_large_textures
tmemSize = 256 if self.isCI else 512
self.ti1.texAddr = None # must be set whenever tex 1 used (and loaded or tiled)
Expand Down
19 changes: 19 additions & 0 deletions fast64_internal/f3d/f3d_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ def fixLargeUVs(obj):
" that are assigned to an empty material slot."
)

# ignore materials using texture references (avoids getTexDimensions throwing an error)
# TODO: find a better way
if (material.f3d_mat.tex0.tex_set and material.f3d_mat.tex0.use_tex_reference) or (
material.f3d_mat.tex1.tex_set and material.f3d_mat.tex1.use_tex_reference
):
continue

if material not in texSizeDict:
texSizeDict[material] = getTexDimensions(material)
if material.f3d_mat.use_large_textures:
Expand Down Expand Up @@ -451,6 +458,18 @@ def saveStaticModel(
for material_index, faces in faces_by_mat.items():
material = obj.material_slots[material_index].material

def try_append_refs(tex):
if tex.tex_set and tex.use_tex_reference and tex.extern_refs:
if len(tex.tex_reference) > 0 and not tex.tex_reference.lower().startswith("0x"):
fModel.reference_to_extern.append(tex.tex_reference)

if len(tex.pal_reference) > 0 and not tex.pal_reference.lower().startswith("0x"):
fModel.reference_to_extern.append(tex.pal_reference)

try_append_refs(material.f3d_mat.tex0)
try_append_refs(material.f3d_mat.tex1)
fModel.reference_to_extern = list(set(fModel.reference_to_extern)) # remove duplicates

if drawLayerField is not None and material.mat_ver > 3:
drawLayer = getattr(material.f3d_mat.draw_layer, drawLayerField)
drawLayerName = drawLayer
Expand Down
2 changes: 1 addition & 1 deletion fast64_internal/z64/exporter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def create_scene(originalSceneObj: Object, transform: Matrix, exportInfo: Export
sceneObj,
transform,
exportInfo,
OOTModel(f"{sceneName}_dl", DLFormat.Static, False),
OOTModel(f"{sceneName}_dl", DLFormat.Static, False, context="scene"),
)
newScene.validateScene()

Expand Down
2 changes: 2 additions & 0 deletions fast64_internal/z64/exporter/room/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ def getRoomShapeModelC(self, textureSettings: TextureExportSettings):
"""Returns the C data of the room model"""
roomModel = CData()

self.roomShape.model.add_refs_externs(roomModel)

for i, entry in enumerate(self.roomShape.dl_entries):
if entry.opaque is not None:
roomModel.append(entry.opaque.to_c(self.roomShape.model.f3d))
Expand Down
9 changes: 1 addition & 8 deletions fast64_internal/z64/exporter/scene/rooms.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,7 @@ def new(
original_room_obj,
roomObj,
roomHeader.roomShape,
model.addSubModel(
OOTModel(
f"{roomName}_dl",
model.DLFormat,
None,
model.draw_config,
)
),
model.addSubModel(OOTModel(f"{roomName}_dl", model.DLFormat, None, model.draw_config, context="scene")),
roomIndex,
sceneName,
exportInfo,
Expand Down
3 changes: 2 additions & 1 deletion fast64_internal/z64/exporter/skeleton/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def ootConvertArmatureToC(
removeVanillaData = settings.removeVanillaData
optimize = settings.optimize

fModel = OOTModel(skeletonName, DLFormat, drawLayer)
fModel = OOTModel(skeletonName, DLFormat, drawLayer, context="skeleton")
skeleton, fModel = ootConvertArmatureToSkeletonWithMesh(
originalArmatureObj, convertTransformMatrix, fModel, skeletonName, not savePNG, drawLayer, optimize
)
Expand Down Expand Up @@ -326,6 +326,7 @@ def ootConvertArmatureToC(
)
skeletonC = skeleton.toC()

fModel.add_refs_externs(data)
data.append(exportData.all())
data.append(skeletonC)

Expand Down
5 changes: 3 additions & 2 deletions fast64_internal/z64/f3d/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def ootConvertMeshToC(
try:
obj, allObjs = ootDuplicateHierarchy(originalObj, None, False, OOTObjectCategorizer())

fModel = OOTModel(obj_name, DLFormat, None)
fModel = OOTModel(obj_name, DLFormat, None, context="dl")
triConverterInfo = TriangleConverterInfo(obj, None, fModel.f3d, finalTransform, getInfoDict(obj))
fMeshes = saveStaticModel(
triConverterInfo, fModel, obj, finalTransform, fModel.name, not saveTextures, False, "oot"
Expand Down Expand Up @@ -108,6 +108,7 @@ def ootConvertMeshToC(
OOTF3DGfxFormatter(ScrollMethod.Vertex, use_draw_layer_suffix=use_draw_layer_suffix),
)

fModel.add_refs_externs(data)
data.append(exportData.all())

if isCustomExport:
Expand Down Expand Up @@ -171,7 +172,7 @@ def execute(self, context):
]

filedata = getImportData(paths)
f3dContext = OOTF3DContext(get_F3D_GBI(), [name], basePath)
f3dContext = OOTF3DContext(get_F3D_GBI(), [name], basePath, context="dl")

# Test for "new" (post-ZAPD) assets system.
is_2025_assets_system = "{\n#include" in filedata
Expand Down
4 changes: 4 additions & 0 deletions fast64_internal/z64/f3d/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class OOTDLExportSettings(PropertyGroup):
default="assets/objects/gameplay_keep",
description="Used in #include for including image files",
)
ignore_segments: BoolProperty(name="Ignore DL Segments", default=False)

def draw_props(self, layout: UILayout):
layout.label(text="Object name used for export.", icon="INFO")
Expand All @@ -46,6 +47,7 @@ def draw_props(self, layout: UILayout):

layout.prop(self, "isCustom")
layout.prop(self, "removeVanillaData")
layout.prop(self, "ignore_segments")


class OOTDLImportSettings(PropertyGroup):
Expand All @@ -61,6 +63,7 @@ class OOTDLImportSettings(PropertyGroup):
flipbookArrayIndex2D: IntProperty(name="Index if 2D Array", default=0, min=0)
autoDetectActorScale: BoolProperty(name="Auto Detect Actor Scale", default=True)
actorScale: FloatProperty(name="Actor Scale", min=0, default=10)
ignore_segments: BoolProperty(name="Ignore DL Segments", default=False)

def draw_props(self, layout: UILayout):
prop_split(layout, self, "name", "DL")
Expand All @@ -82,6 +85,7 @@ def draw_props(self, layout: UILayout):
layout.prop(self, "isCustom")
layout.prop(self, "removeDoubles")
layout.prop(self, "importNormals")
layout.prop(self, "ignore_segments")


class OOTDynamicMaterialDrawLayerProperty(PropertyGroup):
Expand Down
2 changes: 1 addition & 1 deletion fast64_internal/z64/importer/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def parseScene(
)

# set scene default registers (see sDefaultDisplayList)
f3dContext = OOTF3DContext(get_F3D_GBI(), [], bpy.path.abspath(bpy.context.scene.ootDecompPath))
f3dContext = OOTF3DContext(get_F3D_GBI(), [], bpy.path.abspath(bpy.context.scene.ootDecompPath), context="scene")
f3dContext.mat().prim_color = (0.5, 0.5, 0.5, 0.5)
f3dContext.mat().env_color = (0.5, 0.5, 0.5, 0.5)

Expand Down
Loading
Loading