Skip to content

Commit

Permalink
Merge branch 'main' into automatically_add_world
Browse files Browse the repository at this point in the history
  • Loading branch information
Lilaa3 authored May 31, 2024
2 parents 6fdf9f4 + 38cda97 commit 14803fc
Show file tree
Hide file tree
Showing 28 changed files with 1,131 additions and 788 deletions.
104 changes: 3 additions & 101 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import bpy
from bpy.utils import register_class, unregister_class
from . import addon_updater_ops
from .fast64_internal.operators import AddWaterBox
from .fast64_internal.panels import SM64_Panel
from .fast64_internal.utility import PluginError, raisePluginError, attemptModifierApply, prop_split, multilineLabel
from .fast64_internal.utility import prop_split, multilineLabel

from .fast64_internal.sm64 import SM64_Properties, sm64_register, sm64_unregister
from .fast64_internal.sm64 import sm64_register, sm64_unregister
from .fast64_internal.sm64.settings.properties import SM64_Properties
from .fast64_internal.sm64.sm64_geolayout_bone import SM64_BoneProperties
from .fast64_internal.sm64.sm64_objects import SM64_ObjectProperties
from .fast64_internal.sm64.sm64_geolayout_utility import createBoneGroups
from .fast64_internal.sm64.sm64_geolayout_parser import generateMetarig

from .fast64_internal.oot import OOT_Properties, oot_register, oot_unregister
from .fast64_internal.oot.props_panel_main import OOT_ObjectProperties
Expand Down Expand Up @@ -54,97 +51,6 @@
)


class AddBoneGroups(bpy.types.Operator):
# set bl_ properties
bl_description = (
"Add bone groups respresenting other node types in " + "SM64 geolayouts (ex. Shadow, Switch, Function)."
)
bl_idname = "object.add_bone_groups"
bl_label = "Add Bone Groups"
bl_options = {"REGISTER", "UNDO", "PRESET"}

# Called on demand (i.e. button press, menu item)
# Can also be called from operator search menu (Spacebar)
def execute(self, context):
try:
if context.mode != "OBJECT" and context.mode != "POSE":
raise PluginError("Operator can only be used in object or pose mode.")
elif context.mode == "POSE":
bpy.ops.object.mode_set(mode="OBJECT")

if len(context.selected_objects) == 0:
raise PluginError("Armature not selected.")
elif type(context.selected_objects[0].data) is not bpy.types.Armature:
raise PluginError("Armature not selected.")

armatureObj = context.selected_objects[0]
createBoneGroups(armatureObj)
except Exception as e:
raisePluginError(self, e)
return {"CANCELLED"}

self.report({"INFO"}, "Created bone groups.")
return {"FINISHED"} # must return a set


class CreateMetarig(bpy.types.Operator):
# set bl_ properties
bl_description = (
"SM64 imported armatures are usually not good for "
+ "rigging. There are often intermediate bones between deform bones "
+ "and they don't usually point to their children. This operator "
+ "creates a metarig on armature layer 4 useful for IK."
)
bl_idname = "object.create_metarig"
bl_label = "Create Animatable Metarig"
bl_options = {"REGISTER", "UNDO", "PRESET"}

# Called on demand (i.e. button press, menu item)
# Can also be called from operator search menu (Spacebar)
def execute(self, context):
try:
if context.mode != "OBJECT":
bpy.ops.object.mode_set(mode="OBJECT")

if len(context.selected_objects) == 0:
raise PluginError("Armature not selected.")
elif type(context.selected_objects[0].data) is not bpy.types.Armature:
raise PluginError("Armature not selected.")

armatureObj = context.selected_objects[0]
generateMetarig(armatureObj)
except Exception as e:
raisePluginError(self, e)
return {"CANCELLED"}

self.report({"INFO"}, "Created metarig.")
return {"FINISHED"} # must return a set


class SM64_AddWaterBox(AddWaterBox):
bl_idname = "object.sm64_add_water_box"

scale: bpy.props.FloatProperty(default=10)
preset: bpy.props.StringProperty(default="Shaded Solid")
matName: bpy.props.StringProperty(default="sm64_water_mat")

def setEmptyType(self, emptyObj):
emptyObj.sm64_obj_type = "Water Box"


class SM64_ArmatureToolsPanel(SM64_Panel):
bl_idname = "SM64_PT_armature_tools"
bl_label = "SM64 Tools"

# called every frame
def draw(self, context):
col = self.layout.column()
col.operator(ArmatureApplyWithMeshOperator.bl_idname)
col.operator(AddBoneGroups.bl_idname)
col.operator(CreateMetarig.bl_idname)
col.operator(SM64_AddWaterBox.bl_idname)


class F3D_GlobalSettingsPanel(bpy.types.Panel):
bl_idname = "F3D_PT_global_settings"
bl_label = "F3D Global Settings"
Expand Down Expand Up @@ -390,12 +296,8 @@ def draw(self, context):
Fast64_Properties,
Fast64_BoneProperties,
Fast64_ObjectProperties,
AddBoneGroups,
CreateMetarig,
SM64_AddWaterBox,
F3D_GlobalSettingsPanel,
Fast64_GlobalSettingsPanel,
SM64_ArmatureToolsPanel,
Fast64_GlobalToolsPanel,
UpgradeF3DMaterialsDialog,
)
Expand Down
20 changes: 20 additions & 0 deletions fast64_internal/f3d/f3d_bleed.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ def bleed_mat(self, cur_fmat: FMaterial, last_mat: FMaterial, bleed_state: int):
commands_bled.commands.remove(None)
else:
commands_bled = self.bleed_cmd_list(cur_fmat.mat_only_DL, bleed_state)
# some syncs may become redundant after bleeding
self.optimize_syncs(commands_bled, bleed_state)
# remove SPEndDisplayList
while SPEndDisplayList() in commands_bled.commands:
commands_bled.commands.remove(SPEndDisplayList())
Expand Down Expand Up @@ -354,6 +356,24 @@ def on_bleed_end(
cmd_list.commands.append(SPEndDisplayList())
self.bled_gfx_lists[cmd_list] = last_mat

# remove syncs if first material, or if no gsDP cmds in material
def optimize_syncs(self, cmd_list: GfxList, bleed_state: int):
no_syncs_needed = {"DPSetPrimColor", "DPSetPrimDepth"} # will not affect rdp
syncs_needed = {"SPSetOtherMode"} # will affect rdp
if bleed_state == self.bleed_start:
while DPPipeSync() in cmd_list.commands:
cmd_list.commands.remove(DPPipeSync())
for cmd in cmd_list.commands:
cmd_name = type(cmd).__name__
if cmd == DPPipeSync():
continue
if "DP" in cmd_name and cmd_name not in no_syncs_needed:
return
if cmd_name in syncs_needed:
return
while DPPipeSync() in cmd_list.commands:
cmd_list.commands.remove(DPPipeSync())

def create_reset_cmds(self, reset_cmd_dict: dict[GbiMacro], default_render_mode: list[str]):
reset_cmds = []
for cmd_type, cmd_use in reset_cmd_dict.items():
Expand Down
8 changes: 4 additions & 4 deletions fast64_internal/f3d/f3d_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1836,7 +1836,9 @@ def createMesh(self, obj, removeDoubles, importNormals, callDeleteMaterialContex
# else:

if importNormals:
mesh.use_auto_smooth = True
# Changed in Blender 4.1: "Meshes now always use custom normals if they exist." (and use_auto_smooth was removed)
if bpy.app.version < (4, 1, 0):
mesh.use_auto_smooth = True
mesh.normals_split_custom_set([f3dVert.normal for f3dVert in self.verts])

for groupName, indices in self.limbGroups.items():
Expand Down Expand Up @@ -2204,13 +2206,11 @@ def parseMacroList(data: str):


def parseMacroArgs(data: str):
end = 0
start = 0
params: "list[str]" = []
parenthesesCount = 0

while end < len(data) - 1:
end += 1
for end in range(len(data)):
if data[end] == "(":
parenthesesCount += 1
elif data[end] == ")":
Expand Down
34 changes: 17 additions & 17 deletions fast64_internal/f3d/f3d_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1315,12 +1315,26 @@ def saveOrGetF3DMaterial(material, fModel, obj, drawLayer, convertTextureData):
+ (("_layer" + str(drawLayer)) if f3dMat.rdp_settings.set_rendermode and drawLayer is not None else "")
+ (("_area" + str(areaIndex)) if f3dMat.set_fog and f3dMat.use_global_fog and areaKey is not None else "")
)
fMaterial = fModel.addMaterial(materialName)
fMaterial.mat_only_DL.commands.append(DPPipeSync())
fMaterial.revert.commands.append(DPPipeSync())

if not material.is_f3d:
raise PluginError("Material named " + material.name + " is not an F3D material.")
fMaterial = fModel.addMaterial(materialName)
useDict = all_combiner_uses(f3dMat)

defaults = create_or_get_world(bpy.context.scene).rdp_defaults
if fModel.f3d.F3DEX_GBI_2:
saveGeoModeDefinitionF3DEX2(fMaterial, f3dMat.rdp_settings, defaults, fModel.matWriteMethod)
else:
saveGeoModeDefinition(fMaterial, f3dMat.rdp_settings, defaults, fModel.matWriteMethod)

# Checking for f3dMat.rdp_settings.g_lighting here will prevent accidental exports,
# There may be some edge case where this isn't desired.
if useDict["Shade"] and f3dMat.rdp_settings.g_lighting and f3dMat.set_lights:
fLights = saveLightsDefinition(fModel, fMaterial, f3dMat, materialName + "_lights")
fMaterial.mat_only_DL.commands.extend([SPSetLights(fLights)])

fMaterial.mat_only_DL.commands.append(DPPipeSync())
fMaterial.revert.commands.append(DPPipeSync())

fMaterial.getScrollData(material, getMaterialScrollDimensions(f3dMat))

Expand Down Expand Up @@ -1412,20 +1426,12 @@ def saveOrGetF3DMaterial(material, fModel, obj, drawLayer, convertTextureData):
]
)

useDict = all_combiner_uses(f3dMat)
multitexManager = MultitexManager(material, fMaterial, fModel)

# Set othermode
if drawLayer is not None:
defaultRM = fModel.getRenderMode(drawLayer)
else:
defaultRM = None

defaults = create_or_get_world(bpy.context.scene).rdp_defaults
if fModel.f3d.F3DEX_GBI_2:
saveGeoModeDefinitionF3DEX2(fMaterial, f3dMat.rdp_settings, defaults, fModel.matWriteMethod)
else:
saveGeoModeDefinition(fMaterial, f3dMat.rdp_settings, defaults, fModel.matWriteMethod)
saveOtherModeHDefinition(
fMaterial,
f3dMat.rdp_settings,
Expand Down Expand Up @@ -1462,12 +1468,6 @@ def saveOrGetF3DMaterial(material, fModel, obj, drawLayer, convertTextureData):
color = exportColor(f3dMat.env_color[0:3]) + [scaleToU8(f3dMat.env_color[3])]
fMaterial.mat_only_DL.commands.append(DPSetEnvColor(*color))

# Checking for f3dMat.rdp_settings.g_lighting here will prevent accidental exports,
# There may be some edge case where this isn't desired.
if useDict["Shade"] and f3dMat.set_lights and f3dMat.rdp_settings.g_lighting:
fLights = saveLightsDefinition(fModel, fMaterial, f3dMat, materialName + "_lights")
fMaterial.mat_only_DL.commands.extend([SPSetLights(fLights)]) # TODO: handle synching: NO NEED?

if useDict["Key"] and f3dMat.set_key:
if material.mat_ver >= 4:
center = f3dMat.key_center
Expand Down
9 changes: 6 additions & 3 deletions fast64_internal/oot/cutscene/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __post_init__(self):
class CutsceneCmdActorCue(CutsceneCmdBase):
"""This class contains a single Actor Cue command data"""

actionID: Optional[int] = None
actionID: Optional[int | str] = None
rot: list[str] = field(default_factory=list)
startPos: list[int] = field(default_factory=list)
endPos: list[int] = field(default_factory=list)
Expand All @@ -69,7 +69,10 @@ def __post_init__(self):
if self.params is not None:
self.startFrame = getInteger(self.params[1])
self.endFrame = getInteger(self.params[2])
self.actionID = getInteger(self.params[0])
try:
self.actionID = getInteger(self.params[0])
except ValueError:
self.actionID = self.params[0]
self.rot = [getRotation(self.params[3]), getRotation(self.params[4]), getRotation(self.params[5])]
self.startPos = [getInteger(self.params[6]), getInteger(self.params[7]), getInteger(self.params[8])]
self.endPos = [getInteger(self.params[9]), getInteger(self.params[10]), getInteger(self.params[11])]
Expand Down Expand Up @@ -302,7 +305,7 @@ class CutsceneCmdLightSetting(CutsceneCmdBase):

isLegacy: Optional[bool] = None
lightSetting: Optional[int] = None
paramNumber: int = 11
paramNumber: int = 14

def __post_init__(self):
if self.params is not None:
Expand Down
19 changes: 14 additions & 5 deletions fast64_internal/oot/cutscene/importer/classes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import bpy
import re

from dataclasses import dataclass
from typing import TYPE_CHECKING
Expand Down Expand Up @@ -53,7 +54,11 @@ def getCmdParams(self, data: str, cmdName: str, paramNumber: int):
"""Returns the list of every parameter of the given command"""

parenthesis = "(" if not cmdName.endswith("(") else ""
params = data.strip().removeprefix(f"{cmdName}{parenthesis}").replace(" ", "").removesuffix(")").split(",")
data = data.strip().removeprefix(f"{cmdName}{parenthesis}").replace(" ", "").removesuffix(")")
if "CS_FLOAT" in data:
data = re.sub(r"CS_FLOAT\([a-fA-F0-9x]*,([0-9e+-.f]*)\)", r"\1", data, re.DOTALL)
data = re.sub(r"CS_FLOAT\([a-fA-F0-9x]*,([0-9e+-.f]*)", r"\1", data, re.DOTALL)
params = data.split(",")
validTimeCmd = cmdName == "CS_TIME" and len(params) == 6 and paramNumber == 5
if len(params) != paramNumber and not validTimeCmd:
raise PluginError(
Expand Down Expand Up @@ -86,8 +91,11 @@ def getParsedCutscenes(self):
for oldName in oldNames:
fileData = fileData.replace(f"{oldName}(", f"{ootCSLegacyToNewCmdNames[oldName]}(")

fileLines: list[str] = []
for line in fileData.split("\n"):
fileLines.append(line.strip())

# parse cutscenes
fileLines = fileData.split("\n")
csData = []
cutsceneList: list[list[str]] = []
foundCutscene = False
Expand All @@ -98,10 +106,11 @@ def getParsedCutscenes(self):

if foundCutscene:
sLine = line.strip()
if not sLine.endswith("),") and sLine.endswith(","):
line += fileLines[fileLines.index(line) + 1].strip()
csCmd = sLine.split("(")[0]
if "CutsceneData " not in line and "};" not in line and csCmd not in ootCutsceneCommandsC:
csData[-1] += line

if len(csData) == 0 or "CS_" in line:
if len(csData) == 0 or sLine.startswith("CS_") and not sLine.startswith("CS_FLOAT"):
csData.append(line)

if "};" in line:
Expand Down
2 changes: 1 addition & 1 deletion fast64_internal/oot/oot_level_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def __init__(self):

class OOTScene(OOTCommonCommands):
def __init__(self, name, model):
self.name = toAlnum(name)
self.name: str = toAlnum(name)
self.write_dummy_room_list = False
self.rooms = {}
self.transitionActorList = set()
Expand Down
9 changes: 8 additions & 1 deletion fast64_internal/oot/oot_level_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,14 @@ def writeTextureArraysExistingScene(fModel: OOTModel, exportPath: str, sceneIncl

def writeOtherSceneProperties(scene, exportInfo, levelC):
modifySceneTable(scene, exportInfo)
editSpecFile(scene, exportInfo, levelC)
editSpecFile(
True,
exportInfo,
levelC.sceneTexturesIsUsed(),
levelC.sceneCutscenesIsUsed(),
len(scene.rooms),
len(levelC.sceneCutscenesC),
)
modifySceneFiles(scene, exportInfo)


Expand Down
Loading

0 comments on commit 14803fc

Please sign in to comment.