Added automatic header modification for actor geolayout exporting.

This commit is contained in:
kurethedead
2020-02-03 12:58:24 -08:00
parent 806ff8337b
commit 2c709cace0
4 changed files with 79 additions and 25 deletions
+3 -1
View File
@@ -128,7 +128,9 @@ Basically, Mario's DMA table starts at 0x4EC000. There is an 8 byte header, and
Often times it is hard to rig an existing SM64 geolayout, as there are many intermediate non-deform bones and bones don't point to their children. To make this easier you can use the 'Create Animatable Metarig' operator in the SM64 Armature Tools header. This will generate a metarig which can be used with IK. The metarig bones will be placed on armature layers 3 and 4.
### Exporting Geolayouts to C
To replace an actor model in decomp, replace its geo.inc.c and model.inc.c contents with the geolayout file and the dl file respectively. Use the contents of the header file to replace existing extern declarations in one of the group header files (ex. mario is in group0.h). Make sure that the name of your geolayout is the same the name of the geolayout you're replacing. Note that any function addresses in geolayout nodes will be converted to decomp function names if possible.
To replace an actor model in decomp, make sure "Write Headers for Actor" is checked and set the correct group name. Make sure the "Name" field is the folder name of the actor, and the directory is the /actors folder.
To replace an actor model manually, replace its geo.inc.c and model.inc.c contents with the geolayout file and the dl file respectively. Use the contents of the header file to replace existing extern declarations in one of the group header files (ex. mario is in group0.h). Make sure that the name of your geolayout is the same the name of the geolayout you're replacing. Note that any function addresses in geolayout nodes will be converted to decomp function names if possible.
### Switch Statements
To create a switch node, and a bone to your armature and set its geolayout type to "Switch". Any bones that will be switched should be parented to this switch bone. The switch bone can do either material, draw layer, or mesh switching.
+19 -2
View File
@@ -355,7 +355,9 @@ class SM64_ExportGeolayoutObject(bpy.types.Operator):
bpy.context.scene.geoTexDir,
bpy.context.scene.geoSaveTextures,
bpy.context.scene.geoSeparateTextureDef,
levelCamera)
levelCamera, bpy.context.scene.geoGroupName if \
bpy.context.scene.geoWriteHeaders else None,
context.scene.geoName)
self.report({'INFO'}, 'Success! Geolayout at ' + \
context.scene.geoExportPath)
elif context.scene.geoExportType == 'Insertable Binary':
@@ -522,7 +524,9 @@ class SM64_ExportGeolayoutArmature(bpy.types.Operator):
bpy.context.scene.geoTexDir,
bpy.context.scene.geoSaveTextures,
bpy.context.scene.geoSeparateTextureDef,
levelCamera)
levelCamera, bpy.context.scene.geoGroupName if \
bpy.context.scene.geoWriteHeaders else None,
context.scene.geoName)
self.report({'INFO'}, 'Success! Geolayout at ' + \
context.scene.geoExportPath)
elif context.scene.geoExportType == 'Insertable Binary':
@@ -641,6 +645,10 @@ class SM64_ExportGeolayoutPanel(bpy.types.Panel):
col.prop(context.scene, 'geoExportType')
if context.scene.geoExportType == 'C':
col.prop(context.scene, 'geoExportPath')
prop_split(col, context.scene, 'geoName', 'Name')
col.prop(context.scene, 'geoWriteHeaders')
if context.scene.geoWriteHeaders:
prop_split(col, context.scene, 'geoGroupName', 'Group Name')
col.prop(context.scene, 'geoSaveTextures')
if context.scene.geoSaveTextures:
col.prop(context.scene, 'geoTexDir')
@@ -1703,6 +1711,12 @@ def register():
name = 'Filepath', subtype = 'FILE_PATH')
bpy.types.Scene.geoIsSegPtr = bpy.props.BoolProperty(
name = 'Is Segmented Address')
bpy.types.Scene.geoName = bpy.props.StringProperty(
name = 'Name', default = 'mario')
bpy.types.Scene.geoGroupName = bpy.props.StringProperty(
name = 'Name', default = 'group0')
bpy.types.Scene.geoWriteHeaders = bpy.props.BoolProperty(
name = 'Write Headers For Actor', default = True)
# Level
bpy.types.Scene.levelLevel = bpy.props.EnumProperty(items = level_enums,
@@ -1824,6 +1838,9 @@ def unregister():
del bpy.types.Scene.geoSeparateTextureDef
del bpy.types.Scene.geoInsertableBinaryPath
del bpy.types.Scene.geoIsSegPtr
del bpy.types.Scene.geoName
del bpy.types.Scene.geoGroupName
del bpy.types.Scene.geoWriteHeaders
# Animation
del bpy.types.Scene.animStartImport
+38 -21
View File
@@ -88,7 +88,7 @@ def appendRevertToGeolayout(geolayoutGraph, fModel):
# Convert to Geolayout
def convertArmatureToGeolayout(armatureObj, obj, convertTransformMatrix,
f3dType, isHWv1, camera):
f3dType, isHWv1, camera, name):
fModel = FModel(f3dType, isHWv1)
@@ -107,12 +107,12 @@ def convertArmatureToGeolayout(armatureObj, obj, convertTransformMatrix,
# Start geolayout
if camera is not None:
geolayoutGraph = GeolayoutGraph(armatureObj.name + '_level')
geolayoutGraph = GeolayoutGraph(name + '_level')
cameraObj = getCameraObj(camera)
meshGeolayout = saveCameraSettingsToGeolayout(
geolayoutGraph, cameraObj, armatureObj)
else:
geolayoutGraph = GeolayoutGraph(armatureObj.name)
geolayoutGraph = GeolayoutGraph(name + "_geo")
rootNode = TransformNode(StartNode())
geolayoutGraph.startGeolayout.nodes.append(rootNode)
meshGeolayout = geolayoutGraph.startGeolayout
@@ -126,7 +126,7 @@ def convertArmatureToGeolayout(armatureObj, obj, convertTransformMatrix,
return geolayoutGraph, fModel
def convertObjectToGeolayout(obj, convertTransformMatrix,
f3dType, isHWv1, camera):
f3dType, isHWv1, camera, name):
fModel = FModel(f3dType, isHWv1)
@@ -135,12 +135,12 @@ def convertObjectToGeolayout(obj, convertTransformMatrix,
# Start geolayout
if camera is not None:
geolayoutGraph = GeolayoutGraph(obj.name + '_level')
geolayoutGraph = GeolayoutGraph(name + '_level')
cameraObj = getCameraObj(camera)
meshGeolayout = saveCameraSettingsToGeolayout(
geolayoutGraph, cameraObj, obj)
else:
geolayoutGraph = GeolayoutGraph(obj.name)
geolayoutGraph = GeolayoutGraph(name + '_geo')
rootNode = TransformNode(StartNode())
geolayoutGraph.startGeolayout.nodes.append(rootNode)
meshGeolayout = geolayoutGraph.startGeolayout
@@ -181,23 +181,25 @@ def convertObjectToGeolayout(obj, convertTransformMatrix,
# C Export
def exportGeolayoutArmatureC(armatureObj, obj, convertTransformMatrix,
f3dType, isHWv1, dirPath, texDir, savePNG, texSeparate, camera):
f3dType, isHWv1, dirPath, texDir, savePNG, texSeparate, camera, groupName, name):
geolayoutGraph, fModel = convertArmatureToGeolayout(armatureObj, obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, name)
saveGeolayoutC(armatureObj.name, geolayoutGraph, fModel, dirPath, texDir,
savePNG, texSeparate)
saveGeolayoutC(name, geolayoutGraph, fModel, dirPath, texDir,
savePNG, texSeparate, groupName)
def exportGeolayoutObjectC(obj, convertTransformMatrix,
f3dType, isHWv1, dirPath, texDir, savePNG, texSeparate, camera):
f3dType, isHWv1, dirPath, texDir, savePNG, texSeparate, camera, groupName, name):
geolayoutGraph, fModel = convertObjectToGeolayout(obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, name)
saveGeolayoutC(obj.name, geolayoutGraph, fModel, dirPath, texDir,
savePNG, texSeparate)
saveGeolayoutC(name, geolayoutGraph, fModel, dirPath, texDir,
savePNG, texSeparate, groupName)
def saveGeolayoutC(dirName, geolayoutGraph, fModel, dirPath, texDir, savePNG,
texSeparate):
texSeparate, groupName):
dirName = toAlnum(dirName)
groupName = toAlnum(groupName)
geoDirPath = os.path.join(dirPath, toAlnum(dirName))
if not os.path.exists(geoDirPath):
@@ -213,6 +215,11 @@ def saveGeolayoutC(dirName, geolayoutGraph, fModel, dirPath, texDir, savePNG,
dlFile = open(modelPath, 'w')
dlFile.write(dlData)
dlFile.close()
# group.c include
if groupName is not None:
groupPathC = os.path.join(dirPath, groupName + ".c")
writeIfNotFound(groupPathC, '#include "' + dirName + '/model.inc.c"', False)
geoPath = os.path.join(geoDirPath, 'geo.inc.c')
geoData = geolayoutGraph.to_c()
@@ -220,25 +227,35 @@ def saveGeolayoutC(dirName, geolayoutGraph, fModel, dirPath, texDir, savePNG,
geoFile.write(geoData)
geoFile.close()
# group_geo.c include
if groupName is not None:
groupPathGeoC = os.path.join(dirPath, groupName + "_geo.c")
writeIfNotFound(groupPathGeoC, '#include "' + dirName + '/geo.inc.c"', False)
headerPath = os.path.join(geoDirPath, 'header.h')
cDefine = geolayoutGraph.to_c_def() + fModel.to_c_def(True)
cDefFile = open(headerPath, 'w')
cDefFile.write(cDefine)
cDefFile.close()
# group.h declaration
if groupName is not None:
groupPathH = os.path.join(dirPath, groupName + ".h")
writeIfNotFound(groupPathH, '#include "' + dirName + '/header.h"', True)
# Insertable Binary
def exportGeolayoutArmatureInsertableBinary(armatureObj, obj,
convertTransformMatrix, f3dType, isHWv1, filepath, camera):
geolayoutGraph, fModel = convertArmatureToGeolayout(armatureObj, obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, armatureObj.name)
saveGeolayoutInsertableBinary(geolayoutGraph, fModel, filepath, f3dType)
def exportGeolayoutObjectInsertableBinary(obj, convertTransformMatrix,
f3dType, isHWv1, filepath, camera):
geolayoutGraph, fModel = convertObjectToGeolayout(obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, obj.name)
saveGeolayoutInsertableBinary(geolayoutGraph, fModel, filepath, f3dType)
@@ -259,7 +276,7 @@ def exportGeolayoutArmatureBinaryBank0(romfile, armatureObj, obj, exportRange,
f3dType, isHWv1, RAMAddr, camera):
geolayoutGraph, fModel = convertArmatureToGeolayout(armatureObj, obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, armatureObj.name)
return saveGeolayoutBinaryBank0(romfile, fModel, geolayoutGraph,
exportRange, levelCommandPos, modelID, textDumpFilePath, RAMAddr)
@@ -269,7 +286,7 @@ def exportGeolayoutObjectBinaryBank0(romfile, obj, exportRange,
f3dType, isHWv1, RAMAddr, camera):
geolayoutGraph, fModel = convertObjectToGeolayout(obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, obj.name)
return saveGeolayoutBinaryBank0(romfile, fModel, geolayoutGraph,
exportRange, levelCommandPos, modelID, textDumpFilePath, RAMAddr)
@@ -320,7 +337,7 @@ def exportGeolayoutArmatureBinary(romfile, armatureObj, obj, exportRange,
textDumpFilePath, f3dType, isHWv1, camera):
geolayoutGraph, fModel = convertArmatureToGeolayout(armatureObj, obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, armatureObj.name)
return saveGeolayoutBinary(romfile, geolayoutGraph, fModel, exportRange,
levelData, levelCommandPos, modelID, textDumpFilePath)
@@ -330,7 +347,7 @@ def exportGeolayoutObjectBinary(romfile, obj, exportRange,
textDumpFilePath, f3dType, isHWv1, camera):
geolayoutGraph, fModel = convertObjectToGeolayout(obj,
convertTransformMatrix, f3dType, isHWv1, camera)
convertTransformMatrix, f3dType, isHWv1, camera, obj.name)
return saveGeolayoutBinary(romfile, geolayoutGraph, fModel, exportRange,
levelData, levelCommandPos, modelID, textDumpFilePath)
+19 -1
View File
@@ -5,6 +5,24 @@ from .sm64_constants import *
from .sm64_geolayout_constants import *
import random
import string
import os
def writeIfNotFound(filePath, stringValue, hasEndIf):
if os.path.exists(filePath):
fileData = open(filePath, 'r')
fileData.seek(0)
stringData = fileData.read()
fileData.close()
if stringValue not in stringData:
if hasEndIf:
stringData = stringData[:-7] + '\n' + stringValue + '\n\n#endif'
else:
stringData += stringValue
fileData = open(filePath, 'w')
fileData.write(stringData)
fileData.close()
else:
raise ValueError(filePath + " does not exist. Group name may be invalid.")
def selectMeshChildrenOnly(obj, ignoreAttr):
ignoreObj = ignoreAttr is not None and getattr(obj, ignoreAttr)
@@ -153,7 +171,7 @@ def prop_split(layout, data, field, name):
split.prop(data, field, text = '')
def toAlnum(name):
if name == '':
if name is None or name == '':
return None
for i in range(len(name)):
if not name[i].isalnum():