From 07bd1ed0ae700de1098e5661a0c7bb67b3d06977 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 7 Nov 2022 18:01:20 -0500 Subject: [PATCH 01/25] WIP SoH Implementation --- fast64_internal/f3d/f3d_gbi.py | 235 ++++++++++++++++++++++ fast64_internal/f3d/f3d_writer.py | 38 +++- fast64_internal/utility.py | 5 + fast64_updater/fast64_updater_status.json | 9 + 4 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 fast64_updater/fast64_updater_status.json diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 775eeb186..ed3b62ffc 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -1983,6 +1983,11 @@ def to_binary(self): + bytearray(self.colorOrNormal) ) + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(pX = self.position[0], pY = self.position[1], pZ = self.position[2], s = self.uv[0], t = self.uv[1], r = self.colorOrNormal[0], g = self.colorOrNormal[1], b = self.colorOrNormal[2], a = self.colorOrNormal[3]) + return data + def to_c(self): if bpy.context.scene.decomp_compatible: return ( @@ -2088,6 +2093,18 @@ def to_c(self): data.source += "\t" + vert.to_c() + ",\n" data.source += "};\n\n" return data + + def to_soh_xml(self): + data = "" + + data += "\n" + + for vert in self.vertices: + data += "\t" + vert.to_soh_xml() + "\n" + + data += "\n" + + return data def to_sm64_decomp_s(self): data = self.name + ":\n" @@ -2174,6 +2191,15 @@ def to_c(self, f3d): raise PluginError("Invalid GfxList format: " + str(self.DLFormat)) return data + def to_soh_xml(self, modelDirPath): + data = "\n" + for command in self.commands: + data += "\t" + command.to_soh_xml() + "\n" + + data += "\n\n" + + return data + def to_sm64_decomp_s(self): data = "glabel " + self.name + "\n" for command in self.commands: @@ -2518,6 +2544,29 @@ def to_c_material_revert(self, gfxFormatter): data.append(self.materialRevert.to_c(self.f3d)) return data + # OTRTODO + def to_soh_xml(self, modelDirPath): + data = "" + + #data += "\n" + for name, mesh in self.meshes.items(): + meshStatic = mesh.to_soh_xml(modelDirPath) + data += meshStatic + #data += "\n" + + #data += "\n" + for name, lod in self.LODGroups.items(): + lodStatic = lod.to_soh_xml(modelDirPath) + data += lodStatic + #data += "\n" + + #data += "\n".format(itemCnt = len(self.materials.items())) + for materialKey, (fMaterial, texDimensions) in self.materials.items(): + data += fMaterial.to_soh_xml(modelDirPath) + #data += "\n" + + return data + def to_c(self, textureExportSettings: TextureExportSettings, gfxFormatter: GfxFormatter): texCSeparate = textureExportSettings.texCSeparate savePNG = textureExportSettings.savePNG @@ -2792,6 +2841,33 @@ def save_binary(self, romfile, f3d, segments): for materialTuple, drawOverride in self.drawMatOverrides.items(): drawOverride.save_binary(romfile, f3d, segments) + + # OTRTODO + def to_soh_xml(self, modelDirPath): + data = "" + + #data += "\n" + if self.cullVertexList is not None: + data += self.cullVertexList.to_soh_xml(modelDirPath) + #data += "\n" + + #data += "\n" + for triGroup in self.triangleGroups: + data += triGroup.to_soh_xml(modelDirPath) + #data += "\n" + + #data += "\n" + for materialTuple, drawOverride in self.drawMatOverrides.items(): + data += drawOverride.to_soh_xml(modelDirPath) + #data += "\n" + + #drawData = "\n" + drawData = self.draw.to_soh_xml(modelDirPath) + #drawData += "\n" + writeXMLData(drawData, os.path.join(modelDirPath, self.draw.name)) + + return data + def to_c(self, f3d, gfxFormatter): staticData = CData() if self.cullVertexList is not None: @@ -2849,6 +2925,25 @@ def save_binary(self, romfile, f3d, segments): self.triList.save_binary(romfile, f3d, segments) self.vertexList.save_binary(romfile) + def to_soh_xml(self, modelDirPath): + vtxData = "" + #vtxData += "\n".format(vtxListName = self.vertexList.name) + vtxData += self.vertexList.to_soh_xml() + #vtxData += "\n" + + writeXMLData(vtxData, os.path.join(modelDirPath, self.vertexList.name)) + + triListData = "" + #triListData += "\n".format(triListName = self.triList.name) + triListData += self.triList.to_soh_xml(modelDirPath) + #triListData += "\n" + writeXMLData(triListData, os.path.join(modelDirPath, self.triList.name)) + + data = "" + #data = vtxData + triListData + + return data + def to_c(self, f3d, gfxFormatter): data = CData() data.append(self.vertexList.to_c()) @@ -2968,6 +3063,23 @@ def save_binary(self, romfile, f3d, segments): if self.revert is not None: self.revert.save_binary(romfile, f3d, segments) + def to_soh_xml(self, modelDirPath): + data = "" + + #matData = "\n" + matData = self.material.to_soh_xml(modelDirPath) + #matData += "\n" + + writeXMLData(matData, os.path.join(modelDirPath, self.material.name)) + + if self.revert is not None: + #revData = "\n" + revData = self.revert.to_soh_xml(modelDirPath) + #revData += "\n" + writeXMLData(revData, os.path.join(modelDirPath, self.revert.name)) + + return data + def to_c(self, f3d): data = CData() data.append(self.material.to_c(f3d)) @@ -3414,6 +3526,11 @@ def to_binary(self, f3d, segments): else: return gsDma1p(f3d.G_VTX, vertPtr, VTX_SIZE * self.count, (self.count - 1) << 4 | self.index) + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(vertexPath = self.vertList.name, index = (self.offset + self.index), count = self.count) + return data + def to_c(self, static=True): header = "gsSPVertex(" if static else "gSPVertex(glistp++, " if not static and bpy.context.scene.decomp_compatible: @@ -3476,6 +3593,11 @@ def to_binary(self, f3d, segments): dlPtr = int.from_bytes(encodeSegmentedAddr(self.displayList.startAddress, segments), "big") return gsDma1p(f3d.G_DL, dlPtr, 0, f3d.G_DL_PUSH) + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(path = self.displayList.name) + return data + def to_c(self, static=True): if static: return "gsSPDisplayList(" + self.displayList.name + ")" @@ -3502,6 +3624,11 @@ def __init__(self, displayList): def get_ptr_offsets(self, f3d): return [4] + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(path = self.displayList.name) + return data + def to_binary(self, f3d, segments): dlPtr = int.from_bytes(encodeSegmentedAddr(self.displayList.startAddress, segments), "big") return gsDma1p(f3d.G_DL, dlPtr, 0, f3d.G_DL_NOPUSH) @@ -3627,6 +3754,10 @@ def to_binary(self, f3d, segments): return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(v0 = self.v0, v1 = self.v1, v2 = self.v2) + return data + def to_c(self, static=True): header = "gsSP1Triangle(" if static else "gSP1Triangle(glistp++, " return header + str(self.v0) + ", " + str(self.v1) + ", " + str(self.v2) + ", " + str(self.flag) + ")" @@ -3711,6 +3842,11 @@ def to_binary(self, f3d, segments): return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(v00 = self.v00, v01 = self.v01, v02 = self.v02, flag0 = self.flag0, v10 = self.v10, v11 = self.v11, v12 = self.v12) + return data + def to_c(self, static=True): header = "gsSP2Triangles(" if static else "gSP2Triangles(glistp++, " return ( @@ -3773,6 +3909,10 @@ def to_c(self, static=True): header = "gsSPCullDisplayList(" if static else "gSPCullDisplayList(glistp++, " return header + str(self.vstart) + ", " + str(self.vend) + ")" + def to_soh_xml(self): + data = "".format(start = self.vstart, end = self.vend) + return data + def to_sm64_decomp_s(self): return "gsSPCullDisplayList " + str(self.vstart) + ", " + str(self.vend) @@ -3820,6 +3960,10 @@ def to_c(self, static=True): header = "gsSPClipRatio(" if static else "gSPClipRatio(glistp++, " return header + str(self.ratio) + ")" + def to_soh_xml(self): + data = "".format(ratio = self.ratio) + return data + def to_sm64_decomp_s(self): return "gsSPClipRatio " + str(self.ratio) @@ -4233,6 +4377,13 @@ def to_binary(self, f3d, segments): return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "" + + data += "".format(s = self.s, t = self.t, level = self.level, tile = self.tile, on = self.on) + + return data + def to_c(self, static=True): header = "gsSPTexture(" if static else "gSPTexture(glistp++, " return ( @@ -4300,6 +4451,10 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_ENDDL, 24, 8), 0 return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): return "gsSPEndDisplayList()" if static else "gSPEndDisplayList(glistp++)" @@ -4400,6 +4555,17 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_SETGEOMETRYMODE, 24, 8), word return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + # OTRTODO + def to_soh_xml(self): + data = "".format(mode = self.mode) + + return data + def to_c(self, static=True): header = "gsDPPipelineMode(" if static else "gDPPipelineMode(glistp++, " return header + self.mode + ")" @@ -4556,6 +4737,10 @@ def to_c(self, static=True): header = "gsDPSetCycleType(" if static else "gDPSetCycleType(glistp++, " return header + self.mode + ")" + def to_soh_xml(self): + data = "" + return data + def to_sm64_decomp_s(self): return "gsDPSetCycleType " + self.mode @@ -4900,6 +5085,16 @@ def to_binary(self, f3d, segments): else: return gsSPSetOtherMode(f3d.G_SETOTHERMODE_L, f3d.G_MDSFT_RENDERMODE, 29, flagWord, f3d) + def to_soh_xml(self): + data = "".format(path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) + + return data + def to_c(self, static=True): header = "gsDPSetTextureImage(" if static else "gDPSetTextureImage(glistp++, " header += self.fmt + ", " + self.siz + ", " + str(self.width) + ", " @@ -5045,6 +5245,12 @@ def to_binary(self, f3d, segments): ) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(a0=self.a0,b0=self.b0,c0=self.c0,d0=self.d0,aa0=self.Aa0,ab0=self.Ab0,ac0=self.Ac0,ad0=self.Ad0,a1=self.a1,b1=self.b1,c1=self.c1,d1=self.d1,aa1=self.Aa1,ab1=self.Ab1,ac1=self.Ac1,ad1=self.Ad1) + + return data + def to_c(self, static=True): a0 = self.a0 # 'G_CCMUX_' + self.a0 b0 = self.b0 # 'G_CCMUX_' + self.b0 @@ -5268,6 +5474,10 @@ def to_binary(self, f3d, segments): ) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(m=self.m, l=self.l, r=self.r, g=self.g, b=self.b, a=self.a) + return data + def to_c(self, static=True): header = "gsDPSetPrimColor(" if static else "gDPSetPrimColor(glistp++, " return ( @@ -5355,6 +5565,11 @@ def __init__(self, t, uls, ult, lrs, lrt): def to_binary(self, f3d, segments): return gsDPLoadTileGeneric(f3d.G_SETTILESIZE, self.t, self.uls, self.ult, self.lrs, self.lrt) + def to_soh_xml(self): + data = "".format(t=self.t, uls=self.uls, ult=self.ult, lrs=self.lrs, lrt=self.lrt) + + return data + def to_c(self, static=True): header = "gsDPSetTileSize(" if static else "gDPSetTileSize(glistp++, " return ( @@ -5471,6 +5686,12 @@ def to_binary(self, f3d, segments): ) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + baseStr = "" + data = baseStr.format(fmt=self.fmt, siz=self.siz, line=self.line, tmem=self.tmem, tile=self.tile, pal=self.palette, cmt0=self.cmt[0], cmt1=self.cmt[1], maskS=self.masks, shiftS=self.shifts, maskT=self.maskt, shiftT=self.shiftt) + + return data + def to_c(self, static=True): # no tabs/line breaks, breaks macros header = "gsDPSetTile(" if static else "gDPSetTile(glistp++, " @@ -5566,6 +5787,11 @@ def to_c(self, static=True): + ")" ) + def to_soh_xml(self): + data = "".format(tile=self.tile, uls=self.uls, ult=self.ult, lrs=self.lrs, dxt=self.dxt) + + return data + def to_sm64_decomp_s(self): return ( "gsDPLoadBlock " @@ -6909,6 +7135,9 @@ def __init__(self): def to_binary(self, f3d, segments): return gsDPNoParam(f3d.G_RDPTILESYNC) + def to_soh_xml(self): + return "" + def to_c(self, static=True): return "gsDPTileSync()" if static else "gDPTileSync(glistp++)" @@ -6928,6 +7157,9 @@ def to_binary(self, f3d, segments): def to_c(self, static=True): return "gsDPPipeSync()" if static else "gDPPipeSync(glistp++)" + + def to_soh_xml(self): + return "" def to_sm64_decomp_s(self): return "gsDPPipeSync" @@ -6943,6 +7175,9 @@ def __init__(self): def to_binary(self, f3d, segments): return gsDPNoParam(f3d.G_RDPLOADSYNC) + def to_soh_xml(self): + return "" + def to_c(self, static=True): return "gsDPLoadSync()" if static else "gDPLoadSync(glistp++)" diff --git a/fast64_internal/f3d/f3d_writer.py b/fast64_internal/f3d/f3d_writer.py index 5d5908673..f0c4c5f24 100644 --- a/fast64_internal/f3d/f3d_writer.py +++ b/fast64_internal/f3d/f3d_writer.py @@ -2821,6 +2821,42 @@ def getWriteMethodFromEnum(enumVal): else: return matWriteMethodEnumDict[enumVal] +def exportF3DtoXML(dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, texDir, savePNG, texSeparate, name, matWriteMethod): + + fModel = FModel(f3dType, isHWv1, name, DLFormat, matWriteMethod) + fMesh = exportF3DCommon(obj, fModel, transformMatrix, True, name, DLFormat, not savePNG) + + modelDirPath = os.path.join(dirPath, toAlnum(name)) + + if not os.path.exists(modelDirPath): + os.makedirs(modelDirPath) + + #gfxFormatter = GfxFormatter(ScrollMethod.Vertex, 64) + exportData = fModel.to_soh_xml(modelDirPath) + staticData = exportData + #dynamicData = exportData.dynamicData + #texC = exportData.textureData + + #if DLFormat == DLFormat.Static: + #staticData.append(dynamicData) + #else: + #geoString = writeMaterialFiles( + # dirPath, + # modelDirPath, + # '#include "actors/' + toAlnum(name) + '/header.h"', + # '#include "actors/' + toAlnum(name) + '/material.inc.h"', + # dynamicData.header, + # dynamicData.source, + # "", + # True, + #) + + #if texSeparate: + #texCFile = open(os.path.join(modelDirPath, "texture.inc.c"), "w", newline="\n") + #texCFile.write(texC.source) + #texCFile.close() + + #writeXMLData(staticData, os.path.join(modelDirPath, "model.xml")) def exportF3DtoC( dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, texDir, savePNG, texSeparate, name, matWriteMethod @@ -2925,7 +2961,7 @@ def execute(self, context): DLName = bpy.context.scene.DLName matWriteMethod = getWriteMethodFromEnum(context.scene.matWriteMethod) - exportF3DtoC( + exportF3DtoXML( exportPath, obj, dlFormat, diff --git a/fast64_internal/utility.py b/fast64_internal/utility.py index 1ed00826b..6959461c1 100644 --- a/fast64_internal/utility.py +++ b/fast64_internal/utility.py @@ -287,6 +287,11 @@ def propertyGroupEquals(oldProp, newProp): return equivalent +def writeXMLData(data, xmlPath): + xmlFile = open(xmlPath, "w", newline="\n", encoding="utf-8") + xmlFile.write(data) + xmlFile.close() + def writeCData(data, headerPath, sourcePath): sourceFile = open(sourcePath, "w", newline="\n", encoding="utf-8") diff --git a/fast64_updater/fast64_updater_status.json b/fast64_updater/fast64_updater_status.json new file mode 100644 index 000000000..952445e49 --- /dev/null +++ b/fast64_updater/fast64_updater_status.json @@ -0,0 +1,9 @@ +{ + "last_check": "", + "backup_date": "", + "update_ready": false, + "ignore": false, + "just_restored": false, + "just_updated": false, + "version_text": {} +} \ No newline at end of file From d47f1282f08562f49d6027d10b94b10148d3a02f Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 7 Nov 2022 20:01:53 -0500 Subject: [PATCH 02/25] Updated Combine LERP implementation --- fast64_internal/f3d/f3d_gbi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index ed3b62ffc..11d35b9c6 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -5246,7 +5246,7 @@ def to_binary(self, f3d, segments): return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") def to_soh_xml(self): - baseStr = "" + baseStr = "" data = baseStr.format(a0=self.a0,b0=self.b0,c0=self.c0,d0=self.d0,aa0=self.Aa0,ab0=self.Ab0,ac0=self.Ac0,ad0=self.Ad0,a1=self.a1,b1=self.b1,c1=self.c1,d1=self.d1,aa1=self.Aa1,ab1=self.Ab1,ac1=self.Ac1,ad1=self.Ad1) return data From ab37b6bcbbf23c2daa61dca7e93c9a5b6b592326 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Mon, 7 Nov 2022 20:34:52 -0500 Subject: [PATCH 03/25] Implemented SetTextureLUT, LoadTile, and LoadTLUTCMD --- fast64_internal/f3d/f3d_gbi.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 11d35b9c6..d8501fa51 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -4153,6 +4153,11 @@ def to_binary(self, f3d, segments): ) return data + # OTRTODO + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): header = ( "gsSPSetLights" + str(len(self.lights.l)) + "(" @@ -4824,6 +4829,10 @@ class DPSetTextureLUT: def __init__(self, mode): self.mode = mode + def to_soh_xml(self): + data = "".format(mode=self.mode) + return data + def to_binary(self, f3d, segments): if self.mode == "G_TT_NONE": modeVal = f3d.G_TT_NONE @@ -5615,6 +5624,10 @@ def __init__(self, t, uls, ult, lrs, lrt): def to_binary(self, f3d, segments): return gsDPLoadTileGeneric(f3d.G_LOADTILE, self.t, self.uls, self.ult, self.lrs, self.lrt) + def to_soh_xml(self): + data = "".format(t=self.t,uls=self.uls,ult=self.ult,lrs=self.lrs,lrt=self.lrt) + return data + def to_c(self, static=True): header = "gsDPLoadTile(" if static else "gDPLoadTile(glistp++, " return ( @@ -5819,6 +5832,10 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_LOADTLUT, 24, 8), _SHIFTL((self.tile), 24, 3) | _SHIFTL((self.count), 14, 10) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(tile=self.tile, count=self.count) + return data + def to_c(self, static=True): header = "gsDPLoadTLUTCmd(" if static else "gDPLoadTLUTCmd(glistp++, " return header + str(self.tile) + ", " + str(self.count) + ")" From 11b87fa548e9f99097ae8882e713de576fe38276 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Mon, 7 Nov 2022 22:52:53 -0600 Subject: [PATCH 04/25] Implemented gbi commands xml parse --- fast64_internal/f3d/f3d_gbi.py | 106 ++++++++++++++++++++++++++++++--- 1 file changed, 99 insertions(+), 7 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index d8501fa51..3be45f7f0 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -1391,7 +1391,7 @@ def RM_OPA_CI(clk): """ MOVEMEM indices - + Each of these indexes an entry in a dmem table which points to a 1-4 word block of dmem in which to store a 1-4 word DMA. @@ -1435,7 +1435,7 @@ def RM_OPA_CI(clk): """ MOVEWORD indices - + Each of these indexes an entry in a dmem table which points to a word in dmem in dmem where an immediate word will be stored. @@ -2093,7 +2093,7 @@ def to_c(self): data.source += "\t" + vert.to_c() + ",\n" data.source += "};\n\n" return data - + def to_soh_xml(self): data = "" @@ -2195,7 +2195,7 @@ def to_soh_xml(self, modelDirPath): data = "\n" for command in self.commands: data += "\t" + command.to_soh_xml() + "\n" - + data += "\n\n" return data @@ -2674,6 +2674,19 @@ def to_c(self, savePNG, texDir, gfxFormatter): dynamicData.append(self.draw.to_c(self.f3d)) return ExportCData(staticData, dynamicData, CData()) + def to_soh_xml(self, savePNG, texDir): + data = "" + for info, texture in self.textures.items(): + if savePNG: + data += texture.to_soh_xml(texDir) + else: + data += texture.to_soh_xml(texDir) + + dynamicData = self.draw.to_soh_xml(texDir) + + writeXMLData(dynamicData, os.path.join(texDir, self.draw.name)) + return data + class FLODGroup: def __init__(self, name, position, alwaysRenderFarthest, DLFormat): @@ -2941,7 +2954,7 @@ def to_soh_xml(self, modelDirPath): data = "" #data = vtxData + triListData - + return data def to_c(self, f3d, gfxFormatter): @@ -4566,7 +4579,7 @@ def to_soh_xml(self): for flag in self.flagList: data += flag + "=\"1\" " - + data += "/>" return data @@ -5918,6 +5931,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "gsDPLoadTextureBlock(" if static else "gDPLoadTextureBlock(glistp++, " return ( @@ -6051,6 +6070,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "gsDPLoadTextureBlockYuv(" if static else "gDPLoadTextureBlockYuv(glistp++, " return ( @@ -6190,6 +6215,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "_gsDPLoadTextureBlock(" if static else "_gDPLoadTextureBlock(glistp++, " return ( @@ -6323,6 +6354,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "gsDPLoadTextureBlock_4b(" if static else "gDPLoadTextureBlock_4b(glistp++, " return ( @@ -6458,6 +6495,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.uls, self.ult, self.lrs, self.lrt, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "gsDPLoadTextureTile(" if static else "gDPLoadTextureTile(glistp++, " return ( @@ -6607,6 +6650,12 @@ def to_binary(self, f3d, segments): ).to_binary(f3d, segments) ) + def to_soh_xml(self): + data = "".format( + self.timg.name, self.fmt, self.width, self.height, self.pal, self.cms[0], self.cms[1], self.cmt[0], self.cmt[1], self.masks, self.maskt, self.shifts, self.shiftt + ) + return data + def to_c(self, static=True): header = "gsDPLoadTextureTile_4b(" if static else "gDPLoadTextureTile_4b(glistp++, " return ( @@ -6719,6 +6768,12 @@ def to_binary(self, f3d, segments): 0, ).to_binary(f3d, segments) + def to_soh_xml(self): + data = "".format( + self.pal, self.dram.name + ) + return data + def to_c(self, static=True): header = "gsDPLoadTLUT_pal16(" if static else "gDPLoadTLUT_pal16(glistp++, " return header + str(self.pal) + ", " + "&" + self.dram.name + ")" @@ -6767,6 +6822,12 @@ def to_binary(self, f3d, segments): 0, ).to_binary(f3d, segments) + def to_soh_xml(self): + data = "".format( + self.dram.name + ) + return data + def to_c(self, static=True): header = "gsDPLoadTLUT_pal256(" if static else "gDPLoadTLUT_pal256(glistp++, " return header + "&" + self.dram.name + ")" @@ -6817,6 +6878,10 @@ def to_binary(self, f3d, segments): 0, ).to_binary(f3d, segments) + def to_soh_xml(self): + data = "".format(self.count, self.tmemaddr, self.dram.name) + return data + def to_c(self, static=True): header = "gsDPLoadTLUT(" if static else "gDPLoadTLUT(glistp++, " return header + str(self.count) + ", " + str(self.tmemaddr) + ", " + "&" + self.dram.name + ")" @@ -6852,6 +6917,10 @@ def to_binary(self, f3d, segments): ), (_SHIFTL(self.k2, 27, 5) | _SHIFTL(self.k3, 18, 9) | _SHIFTL(self.k4, 9, 9) | _SHIFTL(self.k5, 0, 9)) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(self.k0, self.k1, self.k2, self.k3, self.k4, self.k5) + return data + def to_c(self, static=True): header = "gsDPSetConvert(" if static else "gDPSetConvert(glistp++, " return ( @@ -6902,6 +6971,10 @@ def to_binary(self, f3d, segments): ) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(self.wr, self.cr, self.sr) + return data + def to_c(self, static=True): header = "gsDPSetKeyR(" if static else "gDPSetKeyR(glistp++, " return header + str(self.cR) + ", " + str(self.sR) + ", " + str(self.wR) + ")" @@ -6928,6 +7001,10 @@ def to_binary(self, f3d, segments): ) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format(self.cg, self.sg, self.wg, self.cb, self.sb, self.wb) + return data + def to_c(self, static=True): header = "gsDPSetKeyGB(" if static else "gDPSetKeyGB(glistp++, " return ( @@ -7007,6 +7084,12 @@ def to_binary(self, f3d, segments): + words[3].to_bytes(4, "big") ) + def to_soh_xml(self): + data = "".format( + self.xl, self.yl, self.xh, self.yh, self.tile, self.s, self.t, self.dsdx, self.dtdy + ) + return data + def to_c(self, static=True): header = "gsSPTextureRectangle(" if static else "gSPTextureRectangle(glistp++, " return ( @@ -7072,6 +7155,12 @@ def __init__(self, xl, yl, xh, yh, tile, s, t, dsdx=4 << 10, dtdy=1 << 10): def to_binary(self, f3d, segments): raise PluginError("SPScisTextureRectangle not implemented for binary.") + def to_soh_xml(self): + data = "".format( + self.xl, self.yl, self.xh, self.yh, self.tile, self.s, self.t, self.dsdx, self.dtdy + ) + return data + def to_c(self, static=True): if static: raise PluginError("SPScisTextureRectangle is dynamic only.") @@ -7135,6 +7224,9 @@ def __init__(self): def to_binary(self, f3d, segments): return gsDPNoParam(f3d.G_RDPFULLSYNC) + def to_soh_xml(self): + return "" + def to_c(self, static=True): return "gsDPFullSync()" if static else "gDPFullSync(glistp++)" @@ -7174,7 +7266,7 @@ def to_binary(self, f3d, segments): def to_c(self, static=True): return "gsDPPipeSync()" if static else "gDPPipeSync(glistp++)" - + def to_soh_xml(self): return "" From f81bb27af1d5e889f34282d43b732db24a0eccb9 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Tue, 8 Nov 2022 00:14:47 -0600 Subject: [PATCH 05/25] Implemented remaining commands --- fast64_internal/f3d/f3d_gbi.py | 259 +++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 3be45f7f0..8e8e470c6 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2747,6 +2747,18 @@ def to_c(self, f3d, gfxFormatter): dynamicData.append(self.draw.to_c(f3d)) return staticData, dynamicData + def to_soh_xml(self, f3d): + self.create_data() + + staticData = "" + dynamicData = "" + staticData += self.vertexList.to_soh_xml() + for displayList in self.subdraws: + if displayList is not None: + dynamicData += displayList.to_soh_xml(f3d) + dynamicData += self.draw.to_soh_xml(f3d) + return staticData, dynamicData + def create_data(self): if self.drawCommandsBuilt: return @@ -3124,6 +3136,17 @@ def __hash__(self): def to_binary(self): return bytearray(self.color + [0x00] + self.color + [0x00] + self.normal + [0x00] + [0x00] * 4) + def to_soh_xml(self): + data = "".format( + self.color[0], + self.color[1], + self.color[2], + self.normal[0], + self.normal[1], + self.normal[2] + ) + return data + def to_c(self): return ",".join( ( @@ -3181,6 +3204,14 @@ def __hash__(self): def to_binary(self): return bytearray(self.color + [0x00] + self.color + [0x00]) + def to_soh_xml(self): + data = "".format( + self.color[0], + self.color[1], + self.color[2] + ) + return data + def to_c(self): return ", ".join( ( @@ -3226,6 +3257,15 @@ def to_binary(self): + self.y2.to_bytes(4, "big") ) + def to_soh_xml(self): + data = "".format( + self.x1, + self.y1, + self.x2, + self.y2 + ) + return data + def to_c(self): return ( "Hilite " @@ -3292,6 +3332,13 @@ def to_binary(self): data += self.l[i].to_binary() return data + def to_soh_xml(self): + data = "".format(len(self.l)) + for light in self.l: + data += "\t" + light.to_soh_xml() + "\n" + data += "" + return data + def to_c(self): data = CData() data.header = "extern Lights" + str(len(self.l)) + " " + self.name + ";\n" @@ -3322,6 +3369,13 @@ def __init__(self, name): def to_binary(self): return self.l[0].to_binary() + self.l[1].to_binary() + def to_soh_xml(self): + data = "" + for light in self.l: + data += "\t" + light.to_soh_xml() + "\n" + data += "" + return data + def to_c(self): # {{}} => lookat, light array, # {{}} => light, light_t @@ -3492,6 +3546,12 @@ def to_binary(self, f3d, segments): else: return gsDma1p(f3d.G_MTX, matPtr, MTX_SIZE, self.param) + def to_soh_xml(self): + data = "".format( + self.matrix.name, self.param + ) + return data + def to_c(self, static=True): header = "gsSPMatrix(" if static else "gSPMatrix(glistp++, " if not static and bpy.context.scene.decomp_compatible: @@ -3584,6 +3644,12 @@ def to_binary(self, f3d, segments): else: return gsDma1p(f3d.G_MOVEMEM, vpPtr, VP_SIZE, f3d.G_MV_VIEWPORT) + def to_soh_xml(self): + data = "".format( + self.viewport.name + ) + return data + def to_c(self, static=True): header = "gsSPViewport(" if static else "gSPViewport(glistp++, " return header + "&" + self.viewport.name + ")" @@ -3795,6 +3861,12 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_LINE3D, 24, 8), _gsSPLine3D_w1f(self.v0, self.v1, 0, self.flag, f3d) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format( + self.v0, self.v1, self.flag + ) + return data + def to_c(self, static=True): header = "gsSPLine3D(" if static else "gSPLine3D(glistp++, " return header + str(self.v0) + ", " + str(self.v1) + ", " + str(self.flag) + ")" @@ -3820,6 +3892,12 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_LINE3D, 24, 8), _gsSPLine3D_w1f(self.v0, self.v1, self.wd, self.flag, f3d) return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "".format( + self.v0, self.v1, self.wd, self.flag + ) + return data + def to_c(self, static=True): header = "gsSPLineW3D(" if static else "gSPLineW3D(glistp++, " return header + str(self.v0) + ", " + str(self.v1) + ", " + str(self.wd) + ", " + str(self.flag) + ")" @@ -3941,6 +4019,12 @@ def __init__(self, segment, base): def to_binary(self, f3d, segments): return gsMoveWd(f3d.G_MW_SEGMENT, (self.segment) * 4, self.base, f3d) + def to_soh_xml(self): + data = "".format( + self.segment, self.base + ) + return data + def to_c(self, static=True): header = "gsSPSegment(" if static else "gSPSegment(glistp++, " return header + str(self.segment) + ", " + "0x" + format(self.base, "X") + ")" @@ -4004,6 +4088,12 @@ def to_binary(self, f3d, segments): else: return gsMoveWd(f3d.G_MW_POINTS, (self.vtx) * 40 + (self.where), self.val, f3d) + def to_soh_xml(self): + data = "".format( + self.vtx, self.where, self.val + ) + return data + def to_c(self, static=True): header = "gsSPModifyVertex(" if static else "gSPModifyVertex(glistp++, " return header + str(self.vtx) + ", " + str(self.where) + ", " + str(self.val) + ")" @@ -4041,6 +4131,12 @@ def to_binary(self, f3d, segments): + words1[1].to_bytes(4, "big") ) + def to_soh_xml(self): + data = "".format( + self.dl.name, self.vtx, self.zval + ) + return data + def to_c(self, static=True): dlName = self.dl.name header = "gsSPBranchLessZraw(" if static else "gSPBranchLessZraw(glistp++, " @@ -4071,6 +4167,12 @@ def __init__(self, n): def to_binary(self, f3d, segments): return gsMoveWd(f3d.G_MW_NUMLIGHT, f3d.G_MWO_NUMLIGHT, f3d.NUML(self.n), f3d) + def to_soh_xml(self): + data = "".format( + self.n + ) + return data + def to_c(self, static=True): header = "gsSPNumLights(" if static else "gSPNumLights(glistp++, " return header + str(self.n) + ")" @@ -4099,6 +4201,12 @@ def to_binary(self, f3d, segments): data = gsDma1p(f3d.G_MOVEMEM, lightPtr, LIGHT_SIZE, (lightIndex[self.n] - 1) * 2 + f3d.G_MV_L0) return data + def to_soh_xml(self): + data = "".format( + self.light.name, self.n + ) + return data + def to_c(self, static=True): header = "gsSPLight(" if static else "gSPLight(glistp++, " if not static and bpy.context.scene.decomp_compatible: @@ -4125,6 +4233,12 @@ def to_binary(self, f3d, segments): f3d.G_MW_LIGHTCOL, f3d.getLightMWO_b(self.n), self.col, f3d ) + def to_soh_xml(self): + data = "".format( + self.n, self.col + ) + return data + def to_c(self, static=True): header = "gsSPLightColor(" if static else "gSPLightColor(glistp++, " return header + str(self.n) + ", 0x" + format(self.col, "08X") + ")" @@ -4218,6 +4332,12 @@ def to_binary(self, f3d, segments): light0Ptr = int.from_bytes(encodeSegmentedAddr(self.la.startAddress, segments), "big") return gsSPLookAtX(light0Ptr, f3d) + gsSPLookAtY(light0Ptr + 16, f3d) + def to_soh_xml(self): + data = "".format( + self.la.name + ) + return data + def to_c(self, static=True): header = "gsSPLookAt(" if static else "gSPLookAt(glistp++, " return header + "&" + self.la.name + ")" @@ -4245,6 +4365,12 @@ def to_binary(self, f3d, segments): ((self.height - 1) * 4 + self.hilite.y1) & 0xFFF, ).to_binary(f3d, segments) + def to_soh_xml(self): + data = "".format( + self.tile, self.hilite.name, self.width, self.height + ) + return data + def to_c(self, static=True): header = "gsDPSetHilite1Tile(" if static else "gDPSetHilite1Tile(glistp++, " return ( @@ -4291,6 +4417,12 @@ def to_binary(self, f3d, segments): ((self.height - 1) * 4 + self.hilite.y2) & 0xFFF, ).to_binary(f3d, segments) + def to_soh_xml(self): + data = "".format( + self.tile, self.hilite.name, self.width, self.height + ) + return data + def to_c(self, static=True): header = "gsDPSetHilite2Tile(" if static else "gDPSetHilite2Tile(glistp++, " return ( @@ -4329,6 +4461,12 @@ def __init__(self, fm, fo): def to_binary(self, f3d, segments): return gsMoveWd(f3d.G_MW_FOG, f3d.G_MWO_FOG, (_SHIFTL(self.fm, 16, 16) | _SHIFTL(self.fo, 0, 16)), f3d) + def to_soh_xml(self): + data = "".format( + self.fm, self.fo + ) + return data + def to_c(self, static=True): header = "gsSPFogFactor(" if static else "gSPFogFactor(glistp++, " return header + str(self.fm) + ", " + str(self.fo) + ")" @@ -4356,6 +4494,12 @@ def to_binary(self, f3d, segments): f3d, ) + def to_soh_xml(self): + data = "".format( + self.minVal, self.maxVal + ) + return data + def to_c(self, static=True): header = "gsSPFogPosition(" if static else "gSPFogPosition(glistp++, " return header + str(self.minVal) + ", " + str(self.maxVal) + ")" @@ -4446,6 +4590,12 @@ def __init__(self, s): def to_binary(self, f3d, segments): return gsMoveWd(f3d.G_MW_PERSPNORM, 0, (self.s), f3d) + def to_soh_xml(self): + data = "".format( + self.s + ) + return data + def to_c(self, static=True): header = "gsSPPerspNormalize(" if static else "gSPPerspNormalize(glistp++, " return header + str(self.s) + ")" @@ -4542,6 +4692,11 @@ def to_binary(self, f3d, segments): else: raise PluginError("GeometryMode only available in F3DEX_GBI_2.") + # OTRTODO + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): data = "gsSPGeometryMode(" if static else "gSPGeometryMode(glistp++, " data += ((" | ".join(self.clearFlagList)) if len(self.clearFlagList) > 0 else "0") + ", " @@ -4649,6 +4804,11 @@ def to_binary(self, f3d, segments): else: raise PluginError("LoadGeometryMode only available in F3DEX_GBI_2.") + # OTRTODO + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): data = "gsSPLoadGeometryMode(" if static else "gSPLoadGeometryMode(glistp++, " for flag in self.flagList: @@ -4688,6 +4848,11 @@ def to_binary(self, f3d, segments): sft = getattr(f3d, self.sft) if hasattr(f3d, str(self.sft)) else self.sft return gsSPSetOtherMode(cmd, sft, self.length, data, f3d) + # OTRTODO + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): data = "" for flag in self.flagList: @@ -4778,6 +4943,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_TP_PERSP return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_TEXTPERSP, 1, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetTexturePersp(" if static else "gDPSetTexturePersp(glistp++, " return header + self.mode + ")" @@ -4803,6 +4974,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_TD_DETAIL return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_TEXTDETAIL, 2, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetTextureDetail(" if static else "gDPSetTextureDetail(glistp++, " return header + self.mode + ")" @@ -4826,6 +5003,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_TL_LOD return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_TEXTLOD, 1, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetTextureLOD(" if static else "gDPSetTextureLOD(glistp++, " return header + self.mode + ")" @@ -4882,6 +5065,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_TF_BILERP return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_TEXTFILT, 2, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetTextureFilter(" if static else "gDPSetTextureFilter(glistp++, " return header + self.mode + ")" @@ -4907,6 +5096,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_TC_FILT return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_TEXTCONV, 3, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetTextureConvert(" if static else "gDPSetTextureConvert(glistp++, " return header + self.mode + ")" @@ -4930,6 +5125,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_CK_KEY return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_COMBKEY, 1, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetCombineKey(" if static else "gDPSetCombineKey(glistp++, " return header + self.mode + ")" @@ -4966,6 +5167,12 @@ def to_binary(self, f3d, segments): modeVal = f3d.G_CD_DISABLE return gsSPSetOtherMode(f3d.G_SETOTHERMODE_H, f3d.G_MDSFT_COLORDITHER, 1, modeVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetColorDither(" if static else "gDPSetColorDither(glistp++, " return header + self.mode + ")" @@ -4996,6 +5203,12 @@ def to_binary(self, f3d, segments): else: raise PluginError("SetAlphaDither not available in HW v1.") + def to_soh_xml(self): + data = "".format( + self.mode + ) + return data + def to_c(self, static=True): header = "gsDPSetAlphaDither(" if static else "gDPSetAlphaDither(glistp++, " return header + self.mode + ")" @@ -5021,6 +5234,12 @@ def to_binary(self, f3d, segments): maskVal = f3d.G_AC_DITHER return gsSPSetOtherMode(f3d.G_SETOTHERMODE_L, f3d.G_MDSFT_ALPHACOMPARE, 2, maskVal, f3d) + def to_soh_xml(self): + data = "".format( + self.mask + ) + return data + def to_c(self, static=True): header = "gsDPSetAlphaCompare(" if static else "gDPSetAlphaCompare(glistp++, " return header + self.mask + ")" @@ -5044,6 +5263,12 @@ def to_binary(self, f3d, segments): srcVal = f3d.G_ZS_PRIM return gsSPSetOtherMode(f3d.G_SETOTHERMODE_L, f3d.G_MDSFT_ZSRCSEL, 1, srcVal, f3d) + def to_soh_xml(self): + data = "".format( + self.src + ) + return data + def to_c(self, static=True): header = "gsDPSetDepthSource(" if static else "gDPSetDepthSource(glistp++, " return header + self.src + ")" @@ -5391,6 +5616,12 @@ def __init__(self, r, g, b, a): def to_binary(self, f3d, segments): return sDPRGBColor(f3d.G_SETENVCOLOR, self.r, self.g, self.b, self.a) + def to_soh_xml(self): + data = "".format( + self.r, self.g, self.b, self.a + ) + return data + def to_c(self, static=True): header = "gsDPSetEnvColor(" if static else "gDPSetEnvColor(glistp++, " return header + str(self.r) + ", " + str(self.g) + ", " + str(self.b) + ", " + str(self.a) + ")" @@ -5412,6 +5643,12 @@ def __init__(self, r, g, b, a): def to_binary(self, f3d, segments): return sDPRGBColor(f3d.G_SETBLENDCOLOR, self.r, self.g, self.b, self.a) + def to_soh_xml(self): + data = "".format( + self.r, self.g, self.b, self.a + ) + return data + def to_c(self, static=True): header = "gsDPSetBlendColor(" if static else "gDPSetBlendColor(glistp++, " return header + str(self.r) + ", " + str(self.g) + ", " + str(self.b) + ", " + str(self.a) + ")" @@ -5433,6 +5670,12 @@ def __init__(self, r, g, b, a): def to_binary(self, f3d, segments): return sDPRGBColor(f3d.G_SETFOGCOLOR, self.r, self.g, self.b, self.a) + def to_soh_xml(self): + data = "".format( + self.r, self.g, self.b, self.a + ) + return data + def to_c(self, static=True): header = "gsDPSetFogColor(" if static else "gDPSetFogColor(glistp++, " return header + str(self.r) + ", " + str(self.g) + ", " + str(self.b) + ", " + str(self.a) + ")" @@ -5451,6 +5694,12 @@ def __init__(self, d): def to_binary(self, f3d, segments): return gsDPSetColor(f3d.G_SETFILLCOLOR, self.d) + def to_soh_xml(self): + data = "".format( + self.d + ) + return data + def to_c(self, static=True): header = "gsDPSetFillColor(" if static else "gDPSetFillColor(glistp++, " return header + str(self.d) + ")" @@ -5470,6 +5719,12 @@ def __init__(self, z=0, dz=0): def to_binary(self, f3d, segments): return gsDPSetColor(f3d.G_SETPRIMDEPTH, _SHIFTL(self.z, 16, 16) | _SHIFTL(self.dz, 0, 16)) + def to_soh_xml(self): + data = "".format( + self.z, self.dz + ) + return data + def to_c(self, static=True): header = "gsDPSetPrimDepth(" if static else "gDPSetPrimDepth(glistp++, " return header + str(self.z) + ", " + str(self.dz) + ")" @@ -5547,6 +5802,10 @@ def to_binary(self, f3d, segments): words = _SHIFTL(f3d.G_RDPSETOTHERMODE, 24, 8) | _SHIFTL(self.mode0, 0, 24), self.mode1 return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") + def to_soh_xml(self): + data = "" + return data + def to_c(self, static=True): header = "gsDPSetOtherMode(" if static else "gDPSetOtherMode(glistp++, " From bc0c8aeb782259c6236c95452b5460c668bcd6bc Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Tue, 8 Nov 2022 20:25:24 -0500 Subject: [PATCH 06/25] Auto stash before rebase of "origin/main" --- fast64_internal/f3d/f3d_gbi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 8e8e470c6..2ed6a18bf 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -3600,7 +3600,7 @@ def to_binary(self, f3d, segments): return gsDma1p(f3d.G_VTX, vertPtr, VTX_SIZE * self.count, (self.count - 1) << 4 | self.index) def to_soh_xml(self): - baseStr = "" + baseStr = "{vertexPath}\" Index=\"{index}\" Count=\"{count}\"/>" data = baseStr.format(vertexPath = self.vertList.name, index = (self.offset + self.index), count = self.count) return data @@ -3673,7 +3673,7 @@ def to_binary(self, f3d, segments): return gsDma1p(f3d.G_DL, dlPtr, 0, f3d.G_DL_PUSH) def to_soh_xml(self): - baseStr = "" + baseStr = "{path}\"/>" data = baseStr.format(path = self.displayList.name) return data @@ -3704,7 +3704,7 @@ def get_ptr_offsets(self, f3d): return [4] def to_soh_xml(self): - baseStr = "" + baseStr = "{path}\"/>" data = baseStr.format(path = self.displayList.name) return data @@ -5407,7 +5407,7 @@ def to_binary(self, f3d, segments): return gsSetImage(f3d.G_SETTIMG, fmt, siz, self.width, imagePtr) def to_soh_xml(self): - data = "".format(path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) + data = "{path}\" Format=\"{fmt}\" Size=\"{siz}\" Width=\"{width}\"/>".format(path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) return data From 5d5a91cc835c1e8b7d41a5ce5b6b06a681465f29 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Wed, 9 Nov 2022 00:58:16 -0500 Subject: [PATCH 07/25] Updates to OoT Skeleton for SoH --- fast64_internal/f3d/f3d_gbi.py | 8 +- fast64_internal/oot/oot_skeleton.py | 146 +++++++++++++++++++++++++++- 2 files changed, 148 insertions(+), 6 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 2ed6a18bf..58eefcb37 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -3547,9 +3547,7 @@ def to_binary(self, f3d, segments): return gsDma1p(f3d.G_MTX, matPtr, MTX_SIZE, self.param) def to_soh_xml(self): - data = "".format( - self.matrix.name, self.param - ) + data = "{path}\" Param=\"{param}\"/>".format(path=str(self.matrix), param=self.param) return data def to_c(self, static=True): @@ -3600,8 +3598,8 @@ def to_binary(self, f3d, segments): return gsDma1p(f3d.G_VTX, vertPtr, VTX_SIZE * self.count, (self.count - 1) << 4 | self.index) def to_soh_xml(self): - baseStr = "{vertexPath}\" Index=\"{index}\" Count=\"{count}\"/>" - data = baseStr.format(vertexPath = self.vertList.name, index = (self.offset + self.index), count = self.count) + baseStr = "{vertexPath}\" VertexBufferIndex=\"{bufferIndex}\" VertexOffset=\"{vertexOffset}\" Count=\"{count}\"/>" + data = baseStr.format(vertexPath = self.vertList.name, bufferIndex = self.index, vertexOffset=self.offset, count = self.count) return data def to_c(self, static=True): diff --git a/fast64_internal/oot/oot_skeleton.py b/fast64_internal/oot/oot_skeleton.py index 92c919217..780dd9504 100644 --- a/fast64_internal/oot/oot_skeleton.py +++ b/fast64_internal/oot/oot_skeleton.py @@ -27,6 +27,7 @@ readFile, raisePluginError, writeCData, + writeXMLData, toAlnum, setOrigin, getGroupNameFromIndex, @@ -154,6 +155,36 @@ def isFlexSkeleton(self): def limbsName(self): return self.name + "Limbs" + def toSohXML(self, modelDirPath): + limbData = "" + data = "" + + if self.limbRoot is None: + return data + + limbList = self.createLimbList() + isFlex = self.isFlexSkeleton() + + limbData += "\n".format(lc=self.getNumLimbs(), dlC=self.getNumDLs()) + else: + limbData += "Normal\" LimbCount=\"{lc}\">\n".format(lc=self.getNumLimbs()) + + for limb in limbList: + indLimbData = limb.toSohXML(self.hasLOD) + + writeXMLData(indLimbData, os.path.join(modelDirPath, limb.name())) + + limbData += "\t\n" + + #limbData.append(data) + + limbData += "" + + return limbData + def toC(self): limbData = CData() data = CData() @@ -232,6 +263,23 @@ def __init__( self.children = [] self.inverseRotation = None + def toSohXML(self, isLOD): + data = "\n".format(legTransX=int(round(self.translation[0])),legTransY=int(round(self.translation[1])),legTransZ=int(round(self.translation[2])),firstChildIndex=self.firstChildIndex,siblingIndex=self.nextSiblingIndex,displayList1=DLName) + + return data + def toC(self, isLOD): if not isLOD: data = "StandardLimb " @@ -636,6 +684,102 @@ def ootProcessBone( return nextIndex, lastMaterialName +def ootConvertArmatureToXML( + originalArmatureObj: bpy.types.Object, + convertTransformMatrix: mathutils.Matrix, + f3dType: str, + isHWv1: bool, + DLFormat: DLFormat, + savePNG: bool, + drawLayer: str, + settings: OOTSkeletonExportSettings, +): + if settings.mode != "Generic" and not settings.isCustom: + importInfo = ootSkeletonImportDict[settings.mode] + skeletonName = importInfo.skeletonName + folderName = importInfo.folderName + overlayName = importInfo.actorOverlayName + flipbookUses2DArray = importInfo.flipbookArrayIndex2D is not None + flipbookArrayIndex2D = importInfo.flipbookArrayIndex2D + isLink = importInfo.isLink + else: + skeletonName = toAlnum(settings.name) + folderName = settings.folder + overlayName = settings.actorOverlayName if not settings.isCustom else None + flipbookUses2DArray = settings.flipbookUses2DArray + flipbookArrayIndex2D = settings.flipbookArrayIndex2D if flipbookUses2DArray else None + isLink = False + + exportPath = bpy.path.abspath(settings.customPath) + isCustomExport = settings.isCustom + removeVanillaData = settings.removeVanillaData + optimize = settings.optimize + + fModel = OOTModel(f3dType, isHWv1, skeletonName, DLFormat, drawLayer) + skeleton, fModel = ootConvertArmatureToSkeletonWithMesh( + originalArmatureObj, convertTransformMatrix, fModel, skeletonName, not savePNG, drawLayer, optimize + ) + + if originalArmatureObj.ootSkeleton.LOD is not None: + lodSkeleton, fModel = ootConvertArmatureToSkeletonWithMesh( + originalArmatureObj.ootSkeleton.LOD, + convertTransformMatrix, + fModel, + skeletonName + "_lod", + not savePNG, + drawLayer, + optimize, + ) + else: + lodSkeleton = None + + if lodSkeleton is not None: + skeleton.hasLOD = True + limbList = skeleton.createLimbList() + lodLimbList = lodSkeleton.createLimbList() + + if len(limbList) != len(lodLimbList): + raise PluginError( + originalArmatureObj.name + + " cannot use " + + originalArmatureObj.ootSkeleton.LOD.name + + "as LOD because they do not have the same bone structure." + ) + + for i in range(len(limbList)): + limbList[i].lodDL = lodLimbList[i].DL + limbList[i].isFlex |= lodLimbList[i].isFlex + + #data = CData() + #data.source += '#include "ultra64.h"\n#include "global.h"\n' + #if not isCustomExport: + #data.source += '#include "' + folderName + '.h"\n\n' + #else: + #data.source += "\n" + + data = "" + + path = ootGetPath(exportPath, isCustomExport, "assets/objects/", folderName, False, True) + includeDir = settings.customAssetIncludeDir if settings.isCustom else f"assets/objects/{folderName}" + exportData = fModel.to_soh_xml(path) + skeletonXML = skeleton.toSohXML(path) + + data += exportData + data += skeletonXML + + #if isCustomExport: + # textureArrayData = writeTextureArraysNew(fModel, flipbookArrayIndex2D) + # data.append(textureArrayData) + + writeXMLData(data, os.path.join(path, skeletonName)) + + #if not isCustomExport: + # writeTextureArraysExisting(bpy.context.scene.ootDecompPath, overlayName, isLink, flipbookArrayIndex2D, fModel) + # addIncludeFiles(folderName, path, skeletonName) + # if removeVanillaData: + # ootRemoveSkeleton(path, folderName, skeletonName) + + def ootConvertArmatureToC( originalArmatureObj: bpy.types.Object, @@ -1180,7 +1324,7 @@ def execute(self, context): f3dType = context.scene.f3d_type drawLayer = armatureObj.ootDrawLayer - ootConvertArmatureToC( + ootConvertArmatureToXML( armatureObj, finalTransform, f3dType, isHWv1, DLFormat.Static, saveTextures, drawLayer, exportSettings ) From 757e7d2dfba405b99b57fa49d5e56e6f47aae8a5 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Wed, 9 Nov 2022 19:35:28 -0600 Subject: [PATCH 08/25] Implemented texture export --- fast64_internal/f3d/f3d_gbi.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 58eefcb37..fea34cab5 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2565,6 +2565,8 @@ def to_soh_xml(self, modelDirPath): data += fMaterial.to_soh_xml(modelDirPath) #data += "\n" + self.texturesSavedLastExport = self.save_soh_textures(modelDirPath) + self.freePalettes() return data def to_c(self, textureExportSettings: TextureExportSettings, gfxFormatter: GfxFormatter): @@ -2650,6 +2652,32 @@ def save_textures(self, exportPath): image.filepath = oldpath return texturesSaved + def save_soh_textures(self, exportPath): + # TODO: Saving texture should come from FImage + texturesSaved = 0 + for (image, texInfo), texture in self.textures.items(): + if texInfo[1] == "PAL": + continue + + # remove '.inc.c' + imageFileName = texture.name + + isPacked = image.packed_file is not None + if not isPacked: + image.pack() + oldpath = image.filepath + try: + image.filepath = bpy.path.abspath(os.path.join(exportPath, imageFileName)) + image.save() + texturesSaved += 1 + if not isPacked: + image.unpack() + except Exception as e: + image.filepath = oldpath + raise Exception(str(e)) + image.filepath = oldpath + return texturesSaved + def freePalettes(self): pass From fedd2f88f51facb31cf677f6d1673bc23a05787c Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Wed, 9 Nov 2022 23:20:39 -0500 Subject: [PATCH 09/25] Fixed some commands --- fast64_internal/f3d/f3d_gbi.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index fea34cab5..eb18643d7 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -4876,7 +4876,13 @@ def to_binary(self, f3d, segments): # OTRTODO def to_soh_xml(self): - data = "" + data = "" - data = baseStr.format(fmt=self.fmt, siz=self.siz, line=self.line, tmem=self.tmem, tile=self.tile, pal=self.palette, cmt0=self.cmt[0], cmt1=self.cmt[1], maskS=self.masks, shiftS=self.shifts, maskT=self.maskt, shiftT=self.shiftt) + baseStr = "" + data = baseStr.format(fmt=self.fmt, siz=self.siz, line=self.line, tmem=self.tmem, tile=self.tile, pal=self.palette, cms0=self.cms[0], cms1=self.cms[1], cmt0=self.cmt[0], cmt1=self.cmt[1], maskS=self.masks, shiftS=self.shifts, maskT=self.maskt, shiftT=self.shiftt) return data From 76c90c1d8351d2fd374872f9353b3d61c0ac0f79 Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Thu, 10 Nov 2022 00:14:17 -0500 Subject: [PATCH 10/25] Bug fixes --- fast64_internal/f3d/f3d_gbi.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index eb18643d7..203ca754d 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2901,8 +2901,9 @@ def to_soh_xml(self, modelDirPath): #data += "\n" if self.cullVertexList is not None: - data += self.cullVertexList.to_soh_xml(modelDirPath) + data += self.cullVertexList.to_soh_xml() #data += "\n" + writeXMLData(data, os.path.join(modelDirPath, self.cullVertexList.name)) #data += "\n" for triGroup in self.triangleGroups: @@ -3960,8 +3961,8 @@ def to_binary(self, f3d, segments): return words[0].to_bytes(4, "big") + words[1].to_bytes(4, "big") def to_soh_xml(self): - baseStr = "" - data = baseStr.format(v00 = self.v00, v01 = self.v01, v02 = self.v02, flag0 = self.flag0, v10 = self.v10, v11 = self.v11, v12 = self.v12) + baseStr = "" + data = baseStr.format(v00 = self.v00, v01 = self.v01, v02 = self.v02, flag0 = self.flag0, v10 = self.v10, v11 = self.v11, v12 = self.v12, flag1 = self.flag1) return data def to_c(self, static=True): @@ -4718,9 +4719,23 @@ def to_binary(self, f3d, segments): else: raise PluginError("GeometryMode only available in F3DEX_GBI_2.") - # OTRTODO def to_soh_xml(self): - data = "" + data = " Date: Fri, 11 Nov 2022 17:05:54 -0600 Subject: [PATCH 11/25] Fixed SetRenderMode --- fast64_internal/f3d/f3d_gbi.py | 9 ++++++--- fast64_internal/utility.py | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 203ca754d..088dd1aba 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2902,8 +2902,8 @@ def to_soh_xml(self, modelDirPath): #data += "\n" if self.cullVertexList is not None: data += self.cullVertexList.to_soh_xml() + writeXMLData(data, os.path.join(modelDirPath, self.cullVertexList.name)) #data += "\n" - writeXMLData(data, os.path.join(modelDirPath, self.cullVertexList.name)) #data += "\n" for triGroup in self.triangleGroups: @@ -5382,8 +5382,11 @@ def to_binary(self, f3d, segments): def to_soh_xml(self): data = " Date: Fri, 11 Nov 2022 21:32:52 -0600 Subject: [PATCH 12/25] Fixed bones and texture export --- fast64_internal/f3d/f3d_gbi.py | 3 --- fast64_internal/oot/oot_skeleton.py | 4 ++-- fast64_internal/utility.py | 3 ++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 088dd1aba..2329fcd40 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2656,9 +2656,6 @@ def save_soh_textures(self, exportPath): # TODO: Saving texture should come from FImage texturesSaved = 0 for (image, texInfo), texture in self.textures.items(): - if texInfo[1] == "PAL": - continue - # remove '.inc.c' imageFileName = texture.name diff --git a/fast64_internal/oot/oot_skeleton.py b/fast64_internal/oot/oot_skeleton.py index 780dd9504..b0e5d77d4 100644 --- a/fast64_internal/oot/oot_skeleton.py +++ b/fast64_internal/oot/oot_skeleton.py @@ -174,9 +174,9 @@ def toSohXML(self, modelDirPath): for limb in limbList: indLimbData = limb.toSohXML(self.hasLOD) - + writeXMLData(indLimbData, os.path.join(modelDirPath, limb.name())) - + limbData += "\t\n" #limbData.append(data) diff --git a/fast64_internal/utility.py b/fast64_internal/utility.py index 3bd030533..6959461c1 100644 --- a/fast64_internal/utility.py +++ b/fast64_internal/utility.py @@ -129,9 +129,10 @@ def parentObject(parent, child): def getFMeshName(vertexGroup, namePrefix, drawLayer, isSkinned): - fMeshName = toAlnum(namePrefix) + fMeshName = toAlnum(namePrefix + ("_" if namePrefix != "" else "") + vertexGroup) if isSkinned: fMeshName += "_skinned" + fMeshName += "_mesh" if drawLayer is not None: fMeshName += "_layer_" + str(drawLayer) return fMeshName From 750e21f41ad8cf7175a0674857ab81f4e11997a6 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Sat, 12 Nov 2022 17:24:28 -0600 Subject: [PATCH 13/25] Implemented internal object path and fixed limbs --- fast64_internal/f3d/f3d_gbi.py | 38 ++++++++++++++----------- fast64_internal/f3d/f3d_writer.py | 7 +++-- fast64_internal/oot/oot_skeleton.py | 27 +++++++++--------- fast64_internal/sm64/sm64_f3d_writer.py | 1 + 4 files changed, 40 insertions(+), 33 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 2329fcd40..de53acc90 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2191,10 +2191,13 @@ def to_c(self, f3d): raise PluginError("Invalid GfxList format: " + str(self.DLFormat)) return data - def to_soh_xml(self, modelDirPath): + def to_soh_xml(self, modelDirPath, objectPath): data = "\n" for command in self.commands: - data += "\t" + command.to_soh_xml() + "\n" + if isinstance(command, SPDisplayList): + data += "\t" + command.to_soh_xml(objectPath) + "\n" + else: + data += "\t" + command.to_soh_xml() + "\n" data += "\n\n" @@ -2545,12 +2548,12 @@ def to_c_material_revert(self, gfxFormatter): return data # OTRTODO - def to_soh_xml(self, modelDirPath): + def to_soh_xml(self, modelDirPath, objectPath): data = "" #data += "\n" for name, mesh in self.meshes.items(): - meshStatic = mesh.to_soh_xml(modelDirPath) + meshStatic = mesh.to_soh_xml(modelDirPath, objectPath) data += meshStatic #data += "\n" @@ -2562,7 +2565,7 @@ def to_soh_xml(self, modelDirPath): #data += "\n".format(itemCnt = len(self.materials.items())) for materialKey, (fMaterial, texDimensions) in self.materials.items(): - data += fMaterial.to_soh_xml(modelDirPath) + data += fMaterial.to_soh_xml(modelDirPath, objectPath) #data += "\n" self.texturesSavedLastExport = self.save_soh_textures(modelDirPath) @@ -2893,7 +2896,7 @@ def save_binary(self, romfile, f3d, segments): # OTRTODO - def to_soh_xml(self, modelDirPath): + def to_soh_xml(self, modelDirPath, objectPath): data = "" #data += "\n" @@ -2904,7 +2907,7 @@ def to_soh_xml(self, modelDirPath): #data += "\n" for triGroup in self.triangleGroups: - data += triGroup.to_soh_xml(modelDirPath) + data += triGroup.to_soh_xml(modelDirPath, objectPath) #data += "\n" #data += "\n" @@ -2913,7 +2916,7 @@ def to_soh_xml(self, modelDirPath): #data += "\n" #drawData = "\n" - drawData = self.draw.to_soh_xml(modelDirPath) + drawData = self.draw.to_soh_xml(modelDirPath, objectPath) #drawData += "\n" writeXMLData(drawData, os.path.join(modelDirPath, self.draw.name)) @@ -2976,7 +2979,7 @@ def save_binary(self, romfile, f3d, segments): self.triList.save_binary(romfile, f3d, segments) self.vertexList.save_binary(romfile) - def to_soh_xml(self, modelDirPath): + def to_soh_xml(self, modelDirPath, objectPath): vtxData = "" #vtxData += "\n".format(vtxListName = self.vertexList.name) vtxData += self.vertexList.to_soh_xml() @@ -2986,7 +2989,7 @@ def to_soh_xml(self, modelDirPath): triListData = "" #triListData += "\n".format(triListName = self.triList.name) - triListData += self.triList.to_soh_xml(modelDirPath) + triListData += self.triList.to_soh_xml(modelDirPath, objectPath) #triListData += "\n" writeXMLData(triListData, os.path.join(modelDirPath, self.triList.name)) @@ -3114,18 +3117,18 @@ def save_binary(self, romfile, f3d, segments): if self.revert is not None: self.revert.save_binary(romfile, f3d, segments) - def to_soh_xml(self, modelDirPath): + def to_soh_xml(self, modelDirPath, objectPath): data = "" #matData = "\n" - matData = self.material.to_soh_xml(modelDirPath) + matData = self.material.to_soh_xml(modelDirPath, objectPath) #matData += "\n" writeXMLData(matData, os.path.join(modelDirPath, self.material.name)) if self.revert is not None: #revData = "\n" - revData = self.revert.to_soh_xml(modelDirPath) + revData = self.revert.to_soh_xml(modelDirPath, objectPath) #revData += "\n" writeXMLData(revData, os.path.join(modelDirPath, self.revert.name)) @@ -3696,9 +3699,10 @@ def to_binary(self, f3d, segments): dlPtr = int.from_bytes(encodeSegmentedAddr(self.displayList.startAddress, segments), "big") return gsDma1p(f3d.G_DL, dlPtr, 0, f3d.G_DL_PUSH) - def to_soh_xml(self): - baseStr = "{path}\"/>" - data = baseStr.format(path = self.displayList.name) + def to_soh_xml(self, objectPath): + name = self.displayList.name + baseStr = "" + data = baseStr.format(path = ">" + name if "0x" in name else (objectPath + "/" + name)) return data def to_c(self, static=True): @@ -5665,7 +5669,7 @@ def to_binary(self, f3d, segments): def to_soh_xml(self): data = "".format( - self.r, self.g, self.b, self.a + r=self.r, g=self.g, b=self.b, a=self.a ) return data diff --git a/fast64_internal/f3d/f3d_writer.py b/fast64_internal/f3d/f3d_writer.py index f0c4c5f24..25dbf8fd2 100644 --- a/fast64_internal/f3d/f3d_writer.py +++ b/fast64_internal/f3d/f3d_writer.py @@ -2821,7 +2821,7 @@ def getWriteMethodFromEnum(enumVal): else: return matWriteMethodEnumDict[enumVal] -def exportF3DtoXML(dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, texDir, savePNG, texSeparate, name, matWriteMethod): +def exportF3DtoXML(dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, texDir, objectPath, savePNG, texSeparate, name, matWriteMethod): fModel = FModel(f3dType, isHWv1, name, DLFormat, matWriteMethod) fMesh = exportF3DCommon(obj, fModel, transformMatrix, True, name, DLFormat, not savePNG) @@ -2832,7 +2832,7 @@ def exportF3DtoXML(dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, tex os.makedirs(modelDirPath) #gfxFormatter = GfxFormatter(ScrollMethod.Vertex, 64) - exportData = fModel.to_soh_xml(modelDirPath) + exportData = fModel.to_soh_xml(modelDirPath, objectPath) staticData = exportData #dynamicData = exportData.dynamicData #texC = exportData.textureData @@ -2956,6 +2956,7 @@ def execute(self, context): f3dType = context.scene.f3d_type isHWv1 = context.scene.isHWv1 texDir = bpy.context.scene.DLTexDir + objectPath = bpy.context.scene.internalObjectPath savePNG = bpy.context.scene.saveTextures separateTexDef = bpy.context.scene.DLSeparateTextureDef DLName = bpy.context.scene.DLName @@ -2969,6 +2970,7 @@ def execute(self, context): f3dType, isHWv1, texDir, + objectPath, savePNG, separateTexDef, DLName, @@ -3008,6 +3010,7 @@ def draw(self, context): prop_split(col, context.scene, "DLName", "Name") prop_split(col, context.scene, "DLExportPath", "Export Path") + prop_split(col, context.scene, "internalObjectPath", "Internal Game Path") prop_split(col, context.scene, "blenderF3DScale", "Scale") prop_split(col, context.scene, "matWriteMethod", "Material Write Method") col.prop(context.scene, "DLExportisStatic") diff --git a/fast64_internal/oot/oot_skeleton.py b/fast64_internal/oot/oot_skeleton.py index b0e5d77d4..6d75d0633 100644 --- a/fast64_internal/oot/oot_skeleton.py +++ b/fast64_internal/oot/oot_skeleton.py @@ -68,9 +68,9 @@ class OOTSkeletonExportSettings(bpy.types.PropertyGroup): flipbookUses2DArray: bpy.props.BoolProperty(name="Has 2D Flipbook Array", default=False) flipbookArrayIndex2D: bpy.props.IntProperty(name="Index if 2D Array", default=0, min=0) customAssetIncludeDir: bpy.props.StringProperty( - name="Asset Include Directory", - default="assets/objects/object_geldb", - description="Used in #include for including image files", + name="Skeleton Output Directory", + default="objects/object_geldb", + description="Used for handling object path", ) optimize: bpy.props.BoolProperty( name="Optimize", @@ -155,7 +155,7 @@ def isFlexSkeleton(self): def limbsName(self): return self.name + "Limbs" - def toSohXML(self, modelDirPath): + def toSohXML(self, modelDirPath, objectPath): limbData = "" data = "" @@ -173,11 +173,11 @@ def toSohXML(self, modelDirPath): limbData += "Normal\" LimbCount=\"{lc}\">\n".format(lc=self.getNumLimbs()) for limb in limbList: - indLimbData = limb.toSohXML(self.hasLOD) + indLimbData = limb.toSohXML(self.hasLOD, objectPath) writeXMLData(indLimbData, os.path.join(modelDirPath, limb.name())) - limbData += "\t\n" + limbData += "\t\n".format(path= objectPath if len(objectPath) > 0 else ">", name=limb.name()) #limbData.append(data) @@ -263,7 +263,7 @@ def __init__( self.children = [] self.inverseRotation = None - def toSohXML(self, isLOD): + def toSohXML(self, isLOD, objectPath): data = " 0 else ">") + DLName data += "LegTransX=\"{legTransX}\" LegTransY=\"{legTransY}\" LegTransZ=\"{legTransZ}\" ChildIndex=\"{firstChildIndex}\" SiblingIndex=\"{siblingIndex}\" DisplayList1=\"{displayList1}\"/>\n".format(legTransX=int(round(self.translation[0])),legTransY=int(round(self.translation[1])),legTransZ=int(round(self.translation[2])),firstChildIndex=self.firstChildIndex,siblingIndex=self.nextSiblingIndex,displayList1=DLName) @@ -645,7 +645,7 @@ def ootProcessBone( # Some skeletons will override the current drawn DL for a limb. # If an override DL is not NULL but the non-override is NULL, then this causes issues. # Thus for cases where we remove geometry, we need to have a dummy DL. - elif bone.use_deform: + elif bone.use_deform or DL is None: DL = OOTDLReference("gEmptyDL") if isinstance(parentLimb, OOTSkeleton): @@ -760,9 +760,8 @@ def ootConvertArmatureToXML( data = "" path = ootGetPath(exportPath, isCustomExport, "assets/objects/", folderName, False, True) - includeDir = settings.customAssetIncludeDir if settings.isCustom else f"assets/objects/{folderName}" - exportData = fModel.to_soh_xml(path) - skeletonXML = skeleton.toSohXML(path) + exportData = fModel.to_soh_xml(path, settings.customAssetIncludeDir) + skeletonXML = skeleton.toSohXML(path, settings.customAssetIncludeDir) data += exportData data += skeletonXML @@ -1358,7 +1357,7 @@ def draw(self, context): if exportSettings.isCustom: prop_split(col, exportSettings, "name", "Skeleton") prop_split(col, exportSettings, "folder", "Object" if not exportSettings.isCustom else "Folder") - prop_split(col, exportSettings, "customAssetIncludeDir", "Asset Include Path") + prop_split(col, exportSettings, "customAssetIncludeDir", "Internal Game Path") prop_split(col, exportSettings, "customPath", "Path") else: prop_split(col, exportSettings, "mode", "Mode") diff --git a/fast64_internal/sm64/sm64_f3d_writer.py b/fast64_internal/sm64/sm64_f3d_writer.py index 3c93f09da..908d0c21b 100644 --- a/fast64_internal/sm64/sm64_f3d_writer.py +++ b/fast64_internal/sm64/sm64_f3d_writer.py @@ -976,6 +976,7 @@ def sm64_dl_writer_register(): bpy.types.Scene.levelDLExport = bpy.props.EnumProperty(items=level_enums, name="Level", default="WF") bpy.types.Scene.DLExportGeoPtr = bpy.props.StringProperty(name="Geolayout Pointer", default="132AA8") bpy.types.Scene.overwriteGeoPtr = bpy.props.BoolProperty(name="Overwrite geolayout pointer", default=False) + bpy.types.Scene.internalObjectPath = bpy.props.StringProperty(name="Directory", default="objects/gameplay_keep") bpy.types.Scene.DLExportPath = bpy.props.StringProperty(name="Directory", subtype="FILE_PATH") bpy.types.Scene.DLExportisStatic = bpy.props.BoolProperty(name="Static DL", default=True) bpy.types.Scene.DLDefinePath = bpy.props.StringProperty(name="Definitions Filepath", subtype="FILE_PATH") From 99ad532d860fc3c89758e22ede445799d537026e Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:28:33 -0600 Subject: [PATCH 14/25] Added path on missing commands --- fast64_internal/f3d/f3d_gbi.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index de53acc90..638308787 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2194,7 +2194,7 @@ def to_c(self, f3d): def to_soh_xml(self, modelDirPath, objectPath): data = "\n" for command in self.commands: - if isinstance(command, SPDisplayList): + if isinstance(command, (SPDisplayList, SPBranchList, SPVertex, DPSetTextureImage)): data += "\t" + command.to_soh_xml(objectPath) + "\n" else: data += "\t" + command.to_soh_xml() + "\n" @@ -3626,9 +3626,9 @@ def to_binary(self, f3d, segments): else: return gsDma1p(f3d.G_VTX, vertPtr, VTX_SIZE * self.count, (self.count - 1) << 4 | self.index) - def to_soh_xml(self): - baseStr = "{vertexPath}\" VertexBufferIndex=\"{bufferIndex}\" VertexOffset=\"{vertexOffset}\" Count=\"{count}\"/>" - data = baseStr.format(vertexPath = self.vertList.name, bufferIndex = self.index, vertexOffset=self.offset, count = self.count) + def to_soh_xml(self, objectPath): + baseStr = "" + data = baseStr.format(parent = objectPath, vertexPath = self.vertList.name, bufferIndex = self.index, vertexOffset=self.offset, count = self.count) return data def to_c(self, static=True): @@ -5457,8 +5457,8 @@ def to_binary(self, f3d, segments): imagePtr = int.from_bytes(encodeSegmentedAddr(self.image.startAddress, segments), "big") return gsSetImage(f3d.G_SETTIMG, fmt, siz, self.width, imagePtr) - def to_soh_xml(self): - data = "{path}\" Format=\"{fmt}\" Size=\"{siz}\" Width=\"{width}\"/>".format(path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) + def to_soh_xml(self, objectPath): + data = "".format(parent = objectPath, path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) return data From 5d5c119934b80c55be4349b728dab17c12e787b8 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Sat, 12 Nov 2022 19:23:35 -0600 Subject: [PATCH 15/25] Fixed wrong path on SetTextureImage --- fast64_internal/f3d/f3d_gbi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 638308787..afa0ed1dd 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -5458,7 +5458,8 @@ def to_binary(self, f3d, segments): return gsSetImage(f3d.G_SETTIMG, fmt, siz, self.width, imagePtr) def to_soh_xml(self, objectPath): - data = "".format(parent = objectPath, path = self.image.name, fmt = self.fmt, siz = self.siz, width = self.width) + name = self.image.name + data = "".format(path = ">" + name if "0x" in name else (objectPath + "/" + name), fmt = self.fmt, siz = self.siz, width = self.width) return data From edf74342edaeab364991ebee3e6a1b056a4ac531 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Sun, 13 Nov 2022 19:00:17 -0600 Subject: [PATCH 16/25] Changed export path behavior and removed _mesh on dl export --- fast64_internal/f3d/f3d_gbi.py | 4 +++- fast64_internal/f3d/f3d_writer.py | 2 +- fast64_internal/oot/oot_skeleton.py | 5 ++--- fast64_internal/utility.py | 8 +++++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index afa0ed1dd..c0904e148 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2328,7 +2328,7 @@ def addLight(self, key, value, fMaterial): self.lights[key] = value def addMesh(self, name, namePrefix, drawLayer, isSkinned, contextObj): - meshName = getFMeshName(name, namePrefix, drawLayer, isSkinned) + meshName = getFMeshName(self, name, namePrefix, drawLayer, isSkinned) checkUniqueBoneNames(self, meshName, name) self.meshes[meshName] = FMesh(meshName, self.DLFormat) @@ -2659,6 +2659,8 @@ def save_soh_textures(self, exportPath): # TODO: Saving texture should come from FImage texturesSaved = 0 for (image, texInfo), texture in self.textures.items(): + # if texInfo[1] == "PAL": + # continue # remove '.inc.c' imageFileName = texture.name diff --git a/fast64_internal/f3d/f3d_writer.py b/fast64_internal/f3d/f3d_writer.py index 25dbf8fd2..f7be5da65 100644 --- a/fast64_internal/f3d/f3d_writer.py +++ b/fast64_internal/f3d/f3d_writer.py @@ -2826,7 +2826,7 @@ def exportF3DtoXML(dirPath, obj, DLFormat, transformMatrix, f3dType, isHWv1, tex fModel = FModel(f3dType, isHWv1, name, DLFormat, matWriteMethod) fMesh = exportF3DCommon(obj, fModel, transformMatrix, True, name, DLFormat, not savePNG) - modelDirPath = os.path.join(dirPath, toAlnum(name)) + modelDirPath = os.path.join(dirPath, objectPath) if not os.path.exists(modelDirPath): os.makedirs(modelDirPath) diff --git a/fast64_internal/oot/oot_skeleton.py b/fast64_internal/oot/oot_skeleton.py index 6d75d0633..ab9ea4365 100644 --- a/fast64_internal/oot/oot_skeleton.py +++ b/fast64_internal/oot/oot_skeleton.py @@ -704,7 +704,7 @@ def ootConvertArmatureToXML( isLink = importInfo.isLink else: skeletonName = toAlnum(settings.name) - folderName = settings.folder + folderName = settings.customAssetIncludeDir overlayName = settings.actorOverlayName if not settings.isCustom else None flipbookUses2DArray = settings.flipbookUses2DArray flipbookArrayIndex2D = settings.flipbookArrayIndex2D if flipbookUses2DArray else None @@ -1356,9 +1356,8 @@ def draw(self, context): col.prop(exportSettings, "isCustom") if exportSettings.isCustom: prop_split(col, exportSettings, "name", "Skeleton") - prop_split(col, exportSettings, "folder", "Object" if not exportSettings.isCustom else "Folder") prop_split(col, exportSettings, "customAssetIncludeDir", "Internal Game Path") - prop_split(col, exportSettings, "customPath", "Path") + prop_split(col, exportSettings, "customPath", "Export Path") else: prop_split(col, exportSettings, "mode", "Mode") if exportSettings.mode == "Generic": diff --git a/fast64_internal/utility.py b/fast64_internal/utility.py index 6959461c1..307fcae82 100644 --- a/fast64_internal/utility.py +++ b/fast64_internal/utility.py @@ -128,11 +128,13 @@ def parentObject(parent, child): bpy.ops.object.parent_set(type="OBJECT", keep_transform=True) -def getFMeshName(vertexGroup, namePrefix, drawLayer, isSkinned): - fMeshName = toAlnum(namePrefix + ("_" if namePrefix != "" else "") + vertexGroup) +def getFMeshName(fModel, vertexGroup, namePrefix, drawLayer, isSkinned): + canMessBones = len(fModel.meshes) > 0 + fMeshName = toAlnum(namePrefix + ("_" if namePrefix != "" else "") + vertexGroup) if canMessBones else toAlnum(namePrefix) if isSkinned: fMeshName += "_skinned" - fMeshName += "_mesh" + if canMessBones: + fMeshName += "_mesh" if drawLayer is not None: fMeshName += "_layer_" + str(drawLayer) return fMeshName From f25ae1f31178f85e2fc096cd313d116ae27f2854 Mon Sep 17 00:00:00 2001 From: Kevin Alexis Contreras <36680385+KiritoDv@users.noreply.github.com> Date: Mon, 14 Nov 2022 10:23:21 -0600 Subject: [PATCH 17/25] Fixed UVs on HD Textures --- fast64_internal/f3d/f3d_writer.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/fast64_internal/f3d/f3d_writer.py b/fast64_internal/f3d/f3d_writer.py index f7be5da65..a4cd89a44 100644 --- a/fast64_internal/f3d/f3d_writer.py +++ b/fast64_internal/f3d/f3d_writer.py @@ -248,19 +248,11 @@ def appendTile(self, sl, sh, tl, th): new_sh = max(sh, self.sh) new_tl = min(tl, self.tl) new_th = max(th, self.th) - newWidth = abs(new_sl - new_sh) + 1 - newHeight = abs(new_tl - new_th) + 1 - - tmemUsage = getTmemWordUsage(self.texFormat, newWidth, newHeight) * 8 * (2 if self.twoTextures else 1) - - if tmemUsage > self.tmemMax: - return False - else: - self.sl = new_sl - self.sh = new_sh - self.tl = new_tl - self.th = new_th - return True + self.sl = new_sl + self.sh = new_sh + self.tl = new_tl + self.th = new_th + return True def tryAdd(self, points): if len(points) == 0: @@ -3009,8 +3001,8 @@ def draw(self, context): col.operator(F3D_ExportDL.bl_idname) prop_split(col, context.scene, "DLName", "Name") - prop_split(col, context.scene, "DLExportPath", "Export Path") prop_split(col, context.scene, "internalObjectPath", "Internal Game Path") + prop_split(col, context.scene, "DLExportPath", "Export Path") prop_split(col, context.scene, "blenderF3DScale", "Scale") prop_split(col, context.scene, "matWriteMethod", "Material Write Method") col.prop(context.scene, "DLExportisStatic") From 15a7761f7c57b4a08dd9bbe0965c132e108bc711 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Wed, 8 Feb 2023 20:50:22 -0600 Subject: [PATCH 18/25] Added texture export as an otr format --- __init__.py | 2 +- fast64_internal/f3d/f3d_gbi.py | 65 +++++++++++++++++++++++++++++-- fast64_internal/f3d/f3d_parser.py | 2 +- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/__init__.py b/__init__.py index afc83898d..392edb4d7 100644 --- a/__init__.py +++ b/__init__.py @@ -462,7 +462,7 @@ def register(): bpy.types.Scene.ignoreTextureRestrictions = bpy.props.BoolProperty(name="Ignore Texture Restrictions") bpy.types.Scene.fullTraceback = bpy.props.BoolProperty(name="Show Full Error Traceback", default=False) bpy.types.Scene.gameEditorMode = bpy.props.EnumProperty( - name="Game", default="SM64", items=gameEditorEnum, update=gameEditorUpdate + name="Game", default="OOT", items=gameEditorEnum, update=gameEditorUpdate ) bpy.types.Scene.saveTextures = bpy.props.BoolProperty(name="Save Textures As PNGs (Breaks CI Textures)") bpy.types.Scene.generateF3DNodeGraph = bpy.props.BoolProperty(name="Generate F3D Node Graph", default=True) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index c0904e148..4246fcb10 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -1,6 +1,7 @@ # Macros are all copied over from gbi.h from typing import Sequence import bpy, os, enum +from struct import pack from ..utility import * @@ -2658,11 +2659,43 @@ def save_textures(self, exportPath): def save_soh_textures(self, exportPath): # TODO: Saving texture should come from FImage texturesSaved = 0 + for (image, texInfo), texture in self.textures.items(): - # if texInfo[1] == "PAL": - # continue - # remove '.inc.c' + if texInfo[1] == "PAL": + continue imageFileName = texture.name + imageOutName = texture.filename[:-6] + format = -1; + + match texture.fmt: + case "G_IM_FMT_RGBA": + match texture.bitSize: + case "G_IM_SIZ_16b": + format = 2 + case "G_IM_SIZ_32b": + format = 1; + case "G_IM_FMT_CI": + match texture.bitSize: + case "G_IM_SIZ_4b": + format = 3; + case "G_IM_SIZ_8b": + format = 4; + case "G_IM_FMT_I": + match texture.bitSize: + case "G_IM_SIZ_4b": + format = 5; + case "G_IM_SIZ_8b": + format = 6; + case "G_IM_FMT_IA": + match texture.bitSize: + case "G_IM_SIZ_4b": + format = 7; + case "G_IM_SIZ_8b": + format = 8; + case "G_IM_SIZ_16b": + format = 9; + + bpy.path.abspath(image.filepath) isPacked = image.packed_file is not None if not isPacked: @@ -2670,7 +2703,31 @@ def save_soh_textures(self, exportPath): oldpath = image.filepath try: image.filepath = bpy.path.abspath(os.path.join(exportPath, imageFileName)) - image.save() + with open(image.filepath, "wb") as file: + # Write OTR Header + # I - Endianness + # I - Resource Type + # I - Game Version + # Q - Magic ID + # I - Resource Version + # QI - Empty space + # QQQI - Fill until 64 bytes + + # Write Texture Header + # I - Texture Type + # I - Width + # I - Height + # I - Flags + # f - H Scale + # f - V Scale + # I - Data Size + + file.write(pack(" Date: Tue, 21 Mar 2023 17:33:56 -0400 Subject: [PATCH 19/25] Updated texture version, all materials export now regardless of use --- fast64_internal/f3d/f3d_gbi.py | 4 +++- fast64_internal/f3d/f3d_writer.py | 27 +++++++++++++-------------- fast64_internal/oot/oot_f3d_writer.py | 5 +++++ fast64_internal/oot/oot_skeleton.py | 3 +-- fast64_internal/utility.py | 3 ++- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index 4246fcb10..e5214d7b7 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -2569,6 +2569,7 @@ def to_soh_xml(self, modelDirPath, objectPath): data += fMaterial.to_soh_xml(modelDirPath, objectPath) #data += "\n" + self.texturesSavedLastExport = self.save_soh_textures(modelDirPath) self.freePalettes() return data @@ -2703,6 +2704,7 @@ def save_soh_textures(self, exportPath): oldpath = image.filepath try: image.filepath = bpy.path.abspath(os.path.join(exportPath, imageFileName)) + print(imageFileName) with open(image.filepath, "wb") as file: # Write OTR Header # I - Endianness @@ -2724,7 +2726,7 @@ def save_soh_textures(self, exportPath): file.write(pack(" str: texFormat = texProp.tex_format name = texProp.tex_reference - texName = fModelName + "_" + (getNameFromPath(name, True) + "_" + texFormat.lower()) + texName = fModelName + "_" + (getNameFromPath(name, True)) + #texName = fModelName + "_" + (getNameFromPath(name, True) + "_" + texFormat.lower()) return texName @@ -1731,14 +1730,14 @@ def saveTextureIndex( nextTmem = tmem + getTmemWordUsage(texFormat, width, height) - if not (bpy.context.scene.ignoreTextureRestrictions or fMaterial.useLargeTextures): - if nextTmem > (512 if texFormat[:2] != "CI" else 256): - raise PluginError( - 'Error in "' - + propName - + '": Textures are too big. Max TMEM size is 4k ' - + "bytes, ex. 2 32x32 RGBA 16 bit textures.\nNote that texture width will be internally padded to 64 bit boundaries." - ) + #if not (bpy.context.scene.ignoreTextureRestrictions or fMaterial.useLargeTextures): + #if nextTmem > (512 if texFormat[:2] != "CI" else 256): + # raise PluginError( + # 'Error in "' + # + propName + # + '": Textures are too big. Max TMEM size is 4k ' + # + "bytes, ex. 2 32x32 RGBA 16 bit textures.\nNote that texture width will be internally padded to 64 bit boundaries." + # ) if width > 1024 or height > 1024: raise PluginError('Error in "' + propName + '": Any side of an image cannot be greater ' + "than 1024.") diff --git a/fast64_internal/oot/oot_f3d_writer.py b/fast64_internal/oot/oot_f3d_writer.py index 2a460c723..1eb6d21f1 100644 --- a/fast64_internal/oot/oot_f3d_writer.py +++ b/fast64_internal/oot/oot_f3d_writer.py @@ -192,7 +192,12 @@ def ootProcessVertexGroup( # This means everything will be saved to one mesh. fMesh = fModel.addMesh(vertexGroup, namePrefix, drawLayerOverride, False, bone) + for mat in meshObj.material_slots: + material = mat.material + fMaterial, texDimensions = saveOrGetF3DMaterial(material, fModel, meshObj, drawLayerOverride, convertTextureData) + for material_index, faces in groupFaces.items(): + matLen = len(meshObj.material_slots) material = meshObj.material_slots[material_index].material checkForF3dMaterialInFaces(meshObj, material) fMaterial, texDimensions = saveOrGetF3DMaterial( diff --git a/fast64_internal/oot/oot_skeleton.py b/fast64_internal/oot/oot_skeleton.py index ab9ea4365..dd6fdcce6 100644 --- a/fast64_internal/oot/oot_skeleton.py +++ b/fast64_internal/oot/oot_skeleton.py @@ -1283,7 +1283,6 @@ def execute(self, context): raisePluginError(self, e) return {"CANCELLED"} # must return a set - class OOT_ExportSkeleton(bpy.types.Operator): # set bl_ properties bl_idname = "object.oot_export_skeleton" @@ -1321,7 +1320,7 @@ def execute(self, context): saveTextures = bpy.context.scene.saveTextures isHWv1 = context.scene.isHWv1 f3dType = context.scene.f3d_type - drawLayer = armatureObj.ootDrawLayer + drawLayer = armatureObj.ootDrawLayer ootConvertArmatureToXML( armatureObj, finalTransform, f3dType, isHWv1, DLFormat.Static, saveTextures, drawLayer, exportSettings diff --git a/fast64_internal/utility.py b/fast64_internal/utility.py index 307fcae82..42271772d 100644 --- a/fast64_internal/utility.py +++ b/fast64_internal/utility.py @@ -130,7 +130,8 @@ def parentObject(parent, child): def getFMeshName(fModel, vertexGroup, namePrefix, drawLayer, isSkinned): canMessBones = len(fModel.meshes) > 0 - fMeshName = toAlnum(namePrefix + ("_" if namePrefix != "" else "") + vertexGroup) if canMessBones else toAlnum(namePrefix) + #fMeshName = toAlnum(namePrefix + ("_" if namePrefix != "" else "") + vertexGroup) if canMessBones else toAlnum(namePrefix) + fMeshName = vertexGroup if canMessBones else toAlnum(namePrefix) if isSkinned: fMeshName += "_skinned" if canMessBones: From acf8d5865071504cd27a8cf24259c33aef5908da Mon Sep 17 00:00:00 2001 From: Nicholas Estelami Date: Sun, 26 Mar 2023 00:19:15 -0400 Subject: [PATCH 20/25] Fixed opcode --- fast64_internal/f3d/f3d_gbi.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fast64_internal/f3d/f3d_gbi.py b/fast64_internal/f3d/f3d_gbi.py index e5214d7b7..494710072 100644 --- a/fast64_internal/f3d/f3d_gbi.py +++ b/fast64_internal/f3d/f3d_gbi.py @@ -4907,9 +4907,17 @@ def to_binary(self, f3d, segments): else: raise PluginError("LoadGeometryMode only available in F3DEX_GBI_2.") - # OTRTODO def to_soh_xml(self): - data = "" + #data = "" + + data = " Date: Thu, 30 Mar 2023 14:06:51 -0400 Subject: [PATCH 21/25] Fixed random blender startup crashes --- fast64_internal/f3d/f3d_material.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fast64_internal/f3d/f3d_material.py b/fast64_internal/f3d/f3d_material.py index a0fdedcca..7fb94ba2a 100644 --- a/fast64_internal/f3d/f3d_material.py +++ b/fast64_internal/f3d/f3d_material.py @@ -1865,6 +1865,7 @@ def load_handler(dummy): lib.reload() bpy.context.scene["f3d_lib_dir"] = None # force node reload! link_f3d_material_library() + break bpy.app.handlers.load_post.append(load_handler) From 1d894dd259f7bed9142e57060ea26b0430e2a4b1 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 24 Oct 2023 22:52:49 +0200 Subject: [PATCH 22/25] Add Collision XML exporting --- fast64_internal/oot/c_writer/oot_level_c.py | 8 ++ fast64_internal/oot/oot_collision.py | 134 +++++++++++++++++++- fast64_internal/oot/oot_level_writer.py | 7 + 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/fast64_internal/oot/c_writer/oot_level_c.py b/fast64_internal/oot/c_writer/oot_level_c.py index fadcc16aa..88ed1b1d3 100644 --- a/fast64_internal/oot/c_writer/oot_level_c.py +++ b/fast64_internal/oot/c_writer/oot_level_c.py @@ -2,6 +2,7 @@ from ...f3d.f3d_gbi import ScrollMethod from ..oot_f3d_writer import OOTGfxFormatter from ..oot_collision import ootCollisionToC +from ..oot_collision import ootCollisionToSohXML from ..oot_cutscene import ootCutsceneDataToC from ..oot_utility import indent from ..oot_constants import ootRoomShapeStructs, ootRoomShapeEntryStructs @@ -780,6 +781,11 @@ def ootSceneCollisionToC(scene): sceneCollisionC.append(ootCollisionToC(scene.collision)) return sceneCollisionC +# Writes the collision data for a scene +def ootSceneCollisionToSohXML(scene): + sceneCollisionSohXML = ootCollisionToSohXML(scene.collision) + return sceneCollisionSohXML + # scene is either None or an OOTScene. This can either be the main scene itself, # or one of the alternate / cutscene headers. @@ -812,6 +818,7 @@ def ootLevelToC(scene, textureExportSettings): levelC.sceneMainC = ootSceneMainToC(scene, 0) levelC.sceneTexturesC = ootSceneTexturesToC(scene, textureExportSettings) levelC.sceneCollisionC = ootSceneCollisionToC(scene) + levelC.sceneCollisionSohXML = ootSceneCollisionToSohXML(scene) levelC.sceneCutscenesC = ootSceneCutscenesToC(scene) for i in range(len(scene.rooms)): @@ -836,6 +843,7 @@ def __init__(self): self.sceneMainC = CData() self.sceneTexturesC = CData() self.sceneCollisionC = CData() + self.sceneCollisionSohXML = "" self.sceneCutscenesC = [] # Files for room segments self.roomMainC = {} diff --git a/fast64_internal/oot/oot_collision.py b/fast64_internal/oot/oot_collision.py index 4394a61b2..ddeaedec3 100644 --- a/fast64_internal/oot/oot_collision.py +++ b/fast64_internal/oot/oot_collision.py @@ -272,6 +272,34 @@ def exportCollisionToC(originalObj, transformMatrix, includeChildren, name, isCu addIncludeFiles(folderName, path, name) +def exportCollisionToSohXML(originalObj, transformMatrix, includeChildren, name, isCustomExport, folderName, exportPath): + collision = OOTCollision(name) + collision.cameraData = OOTCameraData(name) + + if bpy.context.scene.exportHiddenGeometry: + hiddenObjs = unhideAllAndGetHiddenList(bpy.context.scene) + + # Don't remove ignore_render, as we want to resuse this for collision + obj, allObjs = ootDuplicateHierarchy(originalObj, None, True, OOTObjectCategorizer()) + + if bpy.context.scene.exportHiddenGeometry: + hideObjsInList(hiddenObjs) + + try: + exportCollisionCommon(collision, obj, transformMatrix, includeChildren, name) + ootCleanupScene(originalObj, allObjs) + except Exception as e: + ootCleanupScene(originalObj, allObjs) + raise Exception(str(e)) + + collisionXML = ootCollisionToSohXML(collision) + + data = collisionXML + + path = ootGetPath(exportPath, isCustomExport, "assets/objects/", folderName, False, False) + writeXMLData(data, os.path.join(path, name)) + + def updateBounds(position, bounds): if len(bounds) == 0: bounds.append([position[0], position[1], position[2]]) @@ -351,6 +379,10 @@ def ootCollisionVertexToC(vertex): return "{ " + str(vertex.position[0]) + ", " + str(vertex.position[1]) + ", " + str(vertex.position[2]) + " },\n" +def ootCollisionVertexToSohXML(vertex): + return "".format(X=str(vertex.position[0]), Y=str(vertex.position[1]), Z=str(vertex.position[2])) + + def ootCollisionPolygonToC(polygon, ignoreCamera, ignoreActor, ignoreProjectile, enableConveyor, polygonTypeIndex): return ( "{ " @@ -370,12 +402,33 @@ def ootCollisionPolygonToC(polygon, ignoreCamera, ignoreActor, ignoreProjectile, ) +def ootCollisionPolygonToSohXML(polygon, ignoreCamera, ignoreActor, ignoreProjectile, enableConveyor, polygonTypeIndex): + return "".format( + Type=str(polygonTypeIndex), + VertexA=str(polygon.convertShort02(ignoreCamera, ignoreActor, ignoreProjectile)), + VertexB=str(polygon.convertShort04(enableConveyor)), + VertexC=str(polygon.convertShort06()), + NormalX=str(polygon.normal[0] * 32767), + NormalY=str(polygon.normal[1] * 32767), + NormalZ=str(polygon.normal[2] * 32767), + Dist=str(polygon.distance), + ) + + def ootPolygonTypeToC(polygonType): return ( "{ " + format(polygonType.convertHigh(), "#010x") + ", " + format(polygonType.convertLow(), "#010x") + " },\n" ) +def ootPolygonTypeToSohXML(polygonType): + return "".format( + #might be reversed + Data1=polygonType.convertHigh(), + Data2=polygonType.convertLow(), + ) + + def ootWaterBoxToC(waterBox): return ( "{ " @@ -394,6 +447,17 @@ def ootWaterBoxToC(waterBox): ) +def ootWaterBoxToSohXML(waterBox): + return "".format( + Xmin=str(waterBox.low[0]), + Ysurface=str(waterBox.height), + Zmin=str(waterBox.low[1]), + XLength=str(waterBox.high[0] - waterBox.low[0]), + ZLength=str(waterBox.high[1] - waterBox.low[1]), + Properties=str(waterBox.propertyData()) + ) + + def ootCameraDataToC(camData): posC = CData() camC = CData() @@ -562,6 +626,73 @@ def ootCollisionToC(collision): return data +def ootCollisionToSohXML(collision): + #data = CData() + data = "".format( + NumCameraDatas=str(0), #todo: fix + NumCameraPositionDatas=str(0), #todo: fix + NumWaterBoxes=str(len(collision.waterBoxes)) + ) + + for vertex in collision.vertices: + data += ootCollisionVertexToSohXML(vertex) + + polygonIndex = 0 + for polygonType, polygons in collision.polygonGroups.items(): + data += ootPolygonTypeToSohXML(polygonType) + for polygon in polygons: + data += ootCollisionPolygonToSohXML( + polygon, + polygonType.ignoreCameraCollision, + polygonType.ignoreActorCollision, + polygonType.ignoreProjectileCollision, + polygonType.enableConveyor, + polygonIndex, + ) + polygonIndex += 1 + + ''' + todo: camera stuff + + pos, cam = ootCameraDataToSohXML(collision.cameraData) + + if pos is not None: + data += pos + data += cam + ''' + + data += "" + data += "" + + for waterBox in collision.waterBoxes: + data += ootWaterBoxToSohXML(waterBox) + + data += "" + + return data + + class OOT_ExportCollision(bpy.types.Operator): # set bl_ properties bl_idname = "object.oot_export_collision" @@ -588,7 +719,8 @@ def execute(self, context): exportPath = bpy.path.abspath(context.scene.ootColExportPath) filepath = ootGetObjectPath(isCustomExport, exportPath, folderName) - exportCollisionToC(obj, finalTransform, includeChildren, name, isCustomExport, folderName, filepath) + #exportCollisionToC(obj, finalTransform, includeChildren, name, isCustomExport, folderName, filepath) + exportCollisionToSohXML(obj, finalTransform, includeChildren, name, isCustomExport, folderName, filepath) self.report({"INFO"}, "Success!") return {"FINISHED"} diff --git a/fast64_internal/oot/oot_level_writer.py b/fast64_internal/oot/oot_level_writer.py index 366dc166f..27918b3e5 100644 --- a/fast64_internal/oot/oot_level_writer.py +++ b/fast64_internal/oot/oot_level_writer.py @@ -31,6 +31,7 @@ checkObjectReference, writeCDataSourceOnly, writeCDataHeaderOnly, + writeXMLData, ) from .c_writer.oot_scene_bootup import ( @@ -161,10 +162,16 @@ def ootExportSceneToC( ootPreprendSceneIncludes(scene, levelC.sceneTexturesC), os.path.join(levelPath, scene.sceneName() + "_tex.c"), ) + + ''' writeCDataSourceOnly( ootPreprendSceneIncludes(scene, levelC.sceneCollisionC), os.path.join(levelPath, scene.sceneName() + "_col.c"), ) + ''' + + writeXMLData(levelC.sceneCollisionSohXML, os.path.join(levelPath, scene.sceneName() + "_collision")) + if levelC.sceneCutscenesIsUsed(): for i in range(len(levelC.sceneCutscenesC)): writeCDataSourceOnly( From 1afd58080e1722f9c96f370aac16ca8bdf17f73f Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Thu, 26 Oct 2023 18:52:13 +0200 Subject: [PATCH 23/25] Update oot_collision.py --- fast64_internal/oot/oot_collision.py | 87 ++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 24 deletions(-) diff --git a/fast64_internal/oot/oot_collision.py b/fast64_internal/oot/oot_collision.py index ddeaedec3..bef92a749 100644 --- a/fast64_internal/oot/oot_collision.py +++ b/fast64_internal/oot/oot_collision.py @@ -10,6 +10,7 @@ unhideAllAndGetHiddenList, hideObjsInList, writeCData, + writeXMLData, raisePluginError, ) @@ -380,7 +381,7 @@ def ootCollisionVertexToC(vertex): def ootCollisionVertexToSohXML(vertex): - return "".format(X=str(vertex.position[0]), Y=str(vertex.position[1]), Z=str(vertex.position[2])) + return "".format(X=str(vertex.position[0]), Y=str(vertex.position[1]), Z=str(vertex.position[2])) def ootCollisionPolygonToC(polygon, ignoreCamera, ignoreActor, ignoreProjectile, enableConveyor, polygonTypeIndex): @@ -403,7 +404,7 @@ def ootCollisionPolygonToC(polygon, ignoreCamera, ignoreActor, ignoreProjectile, def ootCollisionPolygonToSohXML(polygon, ignoreCamera, ignoreActor, ignoreProjectile, enableConveyor, polygonTypeIndex): - return "".format( + return "".format( Type=str(polygonTypeIndex), VertexA=str(polygon.convertShort02(ignoreCamera, ignoreActor, ignoreProjectile)), VertexB=str(polygon.convertShort04(enableConveyor)), @@ -422,7 +423,7 @@ def ootPolygonTypeToC(polygonType): def ootPolygonTypeToSohXML(polygonType): - return "".format( + return "".format( #might be reversed Data1=polygonType.convertHigh(), Data2=polygonType.convertLow(), @@ -448,7 +449,7 @@ def ootWaterBoxToC(waterBox): def ootWaterBoxToSohXML(waterBox): - return "".format( + return "".format( Xmin=str(waterBox.low[0]), Ysurface=str(waterBox.height), Zmin=str(waterBox.low[1]), @@ -488,6 +489,24 @@ def ootCameraDataToC(camData): return posC, camC +def ootCameraDataToSohXML(camData): + posXML = "" + camXML = "" + exportPosData = False + if len(camData.camPosDict) > 0: + camPosIndex = 0 + for i in range(len(camData.camPosDict)): + camXML += ootCameraEntryToSohXML(camData.camPosDict[i], camData, camPosIndex) + if camData.camPosDict[i].hasPositionData: + posXML += ootCameraPosToSohXML(camData.camPosDict[i]) + camPosIndex += 3 + exportPosData = True + + if not exportPosData: + posXML = None + return posXML, camXML + + def ootCameraPosToC(camPos): return ( "\t{ " @@ -512,6 +531,20 @@ def ootCameraPosToC(camPos): ) +def ootCameraPosToSohXML(camPos): + return "".format( + PosX=str(camPos.position[0]), + PosY=str(camPos.position[1]), + PosZ=str(camPos.position[2]), + RotX=str(camPos.rotation[0]), + RotY=str(camPos.rotation[1]), + RotZ=str(camPos.rotation[2]), + FOV=str(camPos.fov), + JfifID=str(camPos.jfifID), + Unknown=str(camPos.unknown) + ) + + def ootCameraEntryToC(camPos, camData, camPosIndex): return " ".join( ( @@ -524,6 +557,15 @@ def ootCameraEntryToC(camPos, camData, camPosIndex): ) +def ootCameraEntryToSohXML(camPos, camData, camPosIndex): + return "".format( + SType=str(camPos.camSType), + NumData=("3" if camPos.hasPositionData else "0"), + CameraPosDataSeg=(camPosIndex if camPos.hasPositionData else "0") + ) + + + def ootCollisionToC(collision): data = CData() posC, camC = ootCameraDataToC(collision.cameraData) @@ -627,7 +669,6 @@ def ootCollisionToC(collision): def ootCollisionToSohXML(collision): - #data = CData() data = " 0: + polygonIndex = 0 + for polygonType, polygons in collision.polygonGroups.items(): + data += ootPolygonTypeToSohXML(polygonType) + for polygon in polygons: + data += ootCollisionPolygonToSohXML( + polygon, + polygonType.ignoreCameraCollision, + polygonType.ignoreActorCollision, + polygonType.ignoreProjectileCollision, + polygonType.enableConveyor, + polygonIndex, + ) + polygonIndex += 1 - ''' - todo: camera stuff + #prevents crashes when no other cameras exist + data += "" + data += "" pos, cam = ootCameraDataToSohXML(collision.cameraData) if pos is not None: data += pos data += cam - ''' - - data += "" - data += "" for waterBox in collision.waterBoxes: data += ootWaterBoxToSohXML(waterBox) From 1b47b64cac1906cbc702e062d69c16000cbe8171 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Sun, 29 Oct 2023 00:30:11 +0200 Subject: [PATCH 24/25] Remove "Num" attributes --- fast64_internal/oot/oot_collision.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/fast64_internal/oot/oot_collision.py b/fast64_internal/oot/oot_collision.py index bef92a749..c353574b8 100644 --- a/fast64_internal/oot/oot_collision.py +++ b/fast64_internal/oot/oot_collision.py @@ -676,25 +676,16 @@ def ootCollisionToSohXML(collision): MinBoundsY=str(collision.bounds[0][1]), MinBoundsZ=str(collision.bounds[0][2]), ) - data += "MaxBoundsX=\"{MaxBoundsX}\" MaxBoundsY=\"{MaxBoundsY}\" MaxBoundsZ=\"{MaxBoundsZ}\" ".format( + data += "MaxBoundsX=\"{MaxBoundsX}\" MaxBoundsY=\"{MaxBoundsY}\" MaxBoundsZ=\"{MaxBoundsZ}\"".format( MaxBoundsX=str(collision.bounds[1][0]), MaxBoundsY=str(collision.bounds[1][1]), MaxBoundsZ=str(collision.bounds[1][2]), ) else: data += "MinBoundsX=\"0\" MinBoundsY=\"0\" MinBoundsZ=\"0\" " - data += "MaxBoundsX=\"0\" MaxBoundsY=\"0\" MaxBoundsZ=\"0\" " + data += "MaxBoundsX=\"0\" MaxBoundsY=\"0\" MaxBoundsZ=\"0\"" - data += "NumVertices=\"{NumVertices}\" NumPolygons=\"{NumPolygons}\" NumPolygonTypes=\"{NumPolygonTypes}\" ".format( - NumVertices=str(len(collision.vertices)), - NumPolygons=str(collision.polygonCount()), - NumPolygonTypes=str(len(collision.polygonGroups)) - ) - data += "NumCameraDatas=\"{NumCameraDatas}\" NumCameraPositionDatas=\"{NumCameraPositionDatas}\" NumWaterBoxes=\"{NumWaterBoxes}\">".format( - NumCameraDatas=str(0), #todo: fix - NumCameraPositionDatas=str(0), #todo: fix - NumWaterBoxes=str(len(collision.waterBoxes)) - ) + data += ">" for vertex in collision.vertices: data += ootCollisionVertexToSohXML(vertex) From 17e62399f4224b48a472ea82e6d3469005ae6efd Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:16:21 +0100 Subject: [PATCH 25/25] Update oot_collision.py --- fast64_internal/oot/oot_collision.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fast64_internal/oot/oot_collision.py b/fast64_internal/oot/oot_collision.py index c353574b8..9c19f9c14 100644 --- a/fast64_internal/oot/oot_collision.py +++ b/fast64_internal/oot/oot_collision.py @@ -705,10 +705,6 @@ def ootCollisionToSohXML(collision): ) polygonIndex += 1 - #prevents crashes when no other cameras exist - data += "" - data += "" - pos, cam = ootCameraDataToSohXML(collision.cameraData) if pos is not None: