From e453e4fbcedfc36dd23147bd514ca9ded12059ce Mon Sep 17 00:00:00 2001 From: scut Date: Fri, 7 Jul 2023 20:50:06 -0400 Subject: [PATCH 1/4] partially removed useless start geo cmds and slightly optimized skinning to place fMesh in parent node if skinned mesh is the first child --- fast64_internal/sm64/sm64_geolayout_writer.py | 175 +++++++++++------- 1 file changed, 107 insertions(+), 68 deletions(-) diff --git a/fast64_internal/sm64/sm64_geolayout_writer.py b/fast64_internal/sm64/sm64_geolayout_writer.py index 973661019..fba215231 100644 --- a/fast64_internal/sm64/sm64_geolayout_writer.py +++ b/fast64_internal/sm64/sm64_geolayout_writer.py @@ -386,16 +386,13 @@ def convertArmatureToGeolayout( geolayoutGraph = GeolayoutGraph(name + "_geo") if armatureObj.use_render_area: rootNode = TransformNode(StartRenderAreaNode(armatureObj.culling_radius)) - else: - rootNode = TransformNode(StartNode()) - geolayoutGraph.startGeolayout.nodes.append(rootNode) + geolayoutGraph.startGeolayout.nodes.append(rootNode) meshGeolayout = geolayoutGraph.startGeolayout - for i in range(len(startBoneNames)): - startBoneName = startBoneNames[i] - if i > 0: - meshGeolayout.nodes.append(TransformNode(StartNode())) - processBone( + for i, startBoneName in enumerate(startBoneNames): + # if i > 0: + # meshGeolayout.nodes.append(TransformNode(StartNode())) + materialOverrides = processBone( fModel, startBoneName, obj, @@ -404,7 +401,7 @@ def convertArmatureToGeolayout( None, None, None, - meshGeolayout.nodes[i], + i, [], name, meshGeolayout, @@ -412,14 +409,38 @@ def convertArmatureToGeolayout( infoDict, convertTextureData, ) + + def walk(node, fMeshes): + base_node = node.node + if type(base_node) == JumpNode: + if base_node.geolayout: + for node in base_node.geolayout.nodes: + fMeshes = walk(node, fMeshes) + fMesh = getattr(base_node, "fMesh", None) + if fMesh: + if fMeshes.get(base_node.drawLayer, None): + fMeshes[base_node.drawLayer].append(fMesh) + else: + fMeshes[base_node.drawLayer] = [fMesh] + for child in node.children: + fMeshes = walk(child, fMeshes) + return fMeshes + + fMeshes = dict() + for node in geolayoutGraph.startGeolayout.nodes: + fMeshes = walk(node, fMeshes) + + # Must be done after all geometry saved and skinned meshes parented + for (material, specificMat, overrideType) in materialOverrides: + for drawLayer, fMesh_list in fMeshes.items(): + [saveOverrideDraw(obj, fModel, material, specificMat, overrideType, fMesh, drawLayer, convertTextureData) for fMesh in fMesh_list] + generateSwitchOptions(meshGeolayout.nodes[0], meshGeolayout, geolayoutGraph, name) appendRevertToGeolayout(geolayoutGraph, fModel) geolayoutGraph.generateSortedList() if inline: bleed_gfx = GeoLayoutBleed() bleed_gfx.bleed_geo_layout_graph(fModel, geolayoutGraph) - # if DLFormat == DLFormat.GameSpecific: - # geolayoutGraph.convertToDynamic() return geolayoutGraph, fModel @@ -1620,7 +1641,7 @@ def processBone( lastTranslateName, lastRotateName, lastDeformName, - parentTransformNode, + parentTransformNode: Union[int, TransformNode], materialOverrides, namePrefix, geolayout, @@ -1635,7 +1656,7 @@ def processBone( materialOverrides = copy.copy(materialOverrides) if bone.geo_cmd == "Ignore": - return + return materialOverrides # Get translate if lastTranslateName is not None: @@ -1658,7 +1679,14 @@ def processBone( zeroTranslation = isZeroTranslation(translate) zeroRotation = isZeroRotation(rotate) - # hasDL = bone.use_deform + # true when this is the start of the geo layout + # if there is no parent, then instead set the node to be the root of our geo layout + if type(parentTransformNode) == int: + if len(geolayout.nodes) > parentTransformNode: + parentTransformNode = geolayout.nodes[parentTransformNode] + else: + parentTransformNode = None + hasDL = True if bone.geo_cmd in animatableBoneTypes: if bone.geo_cmd == "CustomAnimated": @@ -1671,9 +1699,12 @@ def processBone( if not zeroRotation: node = DisplayListWithOffsetNode(int(bone.draw_layer), hasDL, mathutils.Vector((0, 0, 0))) - parentTransformNode = addParentNode( - parentTransformNode, TranslateRotateNode(1, 0, False, translate, rotate) - ) + if parentTransformNode: + parentTransformNode = addParentNode( + parentTransformNode, TranslateRotateNode(1, 0, False, translate, rotate) + ) + else: + geolayout.nodes.append(TranslateRotateNode(1, 0, False, translate, rotate)) lastTranslateName = boneName lastRotateName = boneName @@ -1795,8 +1826,12 @@ def processBone( # bone.use_deform = False if usedDrawLayers is not None: lastDeformName = boneName - parentTransformNode.children.append(transformNode) - transformNode.parent = parentTransformNode + + if parentTransformNode: + parentTransformNode.children.append(transformNode) + transformNode.parent = parentTransformNode + else: + geolayout.nodes.append(transformNode) else: lastDeformName = boneName if not bone.use_deform: @@ -1824,8 +1859,11 @@ def processBone( node.DLmicrocode = fMesh.draw node.fMesh = fMesh # Used for material override switches - parentTransformNode.children.append(transformNode) - transformNode.parent = parentTransformNode + if parentTransformNode: + parentTransformNode.children.append(transformNode) + transformNode.parent = parentTransformNode + else: + geolayout.nodes.append(transformNode) if ( lastDeformName is not None @@ -1845,15 +1883,16 @@ def processBone( for additionalTransformNode in additionalNodes: transformNode.children.append(additionalTransformNode) additionalTransformNode.parent = transformNode - # print(boneName) + else: - parentTransformNode.children.append(transformNode) - transformNode.parent = parentTransformNode + if parentTransformNode: + parentTransformNode.children.append(transformNode) + transformNode.parent = parentTransformNode + else: + geolayout.nodes.append(transformNode) if not isinstance(transformNode.node, SwitchNode): - # print(boneGroup.name if boneGroup is not None else "Offset") if len(bone.children) > 0: - # print("\tHas Children") if bone.geo_cmd == "Function": raise PluginError( "Function bones cannot have children. They instead affect the next sibling bone in alphabetical order." @@ -1865,7 +1904,7 @@ def processBone( # This is so it can be used for siblings. childrenNames = sorted([bone.name for bone in bone.children]) for name in childrenNames: - processBone( + materialOverrides = processBone( fModel, name, obj, @@ -1882,26 +1921,18 @@ def processBone( infoDict, convertTextureData, ) - # transformNode.children.append(childNode) - # childNode.parent = transformNode # see generateSwitchOptions() for explanation. else: - # print(boneGroup.name if boneGroup is not None else "Offset") if len(bone.children) > 0: - # optionGeolayout = \ - # geolayoutGraph.addGeolayout( - # transformNode, boneName + '_opt0') - # geolayoutGraph.addJumpNode(transformNode, geolayout, - # optionGeolayout) - # optionGeolayout.nodes.append(TransformNode(StartNode())) + # nextStartNode = None nextStartNode = TransformNode(StartNode()) transformNode.children.append(nextStartNode) nextStartNode.parent = transformNode childrenNames = sorted([bone.name for bone in bone.children]) for name in childrenNames: - processBone( + materialOverrides = processBone( fModel, name, obj, @@ -1918,14 +1949,11 @@ def processBone( infoDict, convertTextureData, ) - # transformNode.children.append(childNode) - # childNode.parent = transformNode else: raise PluginError('Switch bone "' + bone.name + '" must have child bones with geometry attached.') bone = armatureObj.data.bones[boneName] - for switchIndex in range(len(bone.switch_options)): - switchOption = bone.switch_options[switchIndex] + for switchIndex, switchOption in enumerate(bone.switch_options): if switchOption.switchType == "Mesh": optionArmature = switchOption.optionArmature if optionArmature is None: @@ -1949,8 +1977,6 @@ def processBone( geolayoutGraph.addJumpNode(transformNode, geolayout, optionGeolayout) continue - # optionNode = addParentNode(switchTransformNode, StartNode()) - optionBoneName = getSwitchOptionBone(optionArmature) optionBone = optionArmature.data.bones[optionBoneName] @@ -1960,9 +1986,10 @@ def processBone( if not zeroRotation or not zeroTranslation: startNode = TransformNode(TranslateRotateNode(1, 0, False, translate, rotate)) + optionGeolayout.nodes.append(startNode) else: - startNode = TransformNode(StartNode()) - optionGeolayout.nodes.append(startNode) + startNode = switchIndex + # startNode = TransformNode(StartNode()) childrenNames = sorted([bone.name for bone in optionBone.children]) for name in childrenNames: @@ -1991,7 +2018,7 @@ def processBone( ) optionObj = optionObjs[0] optionInfoDict = getInfoDict(optionObj) - processBone( + materialOverrides = processBone( fModel, name, optionObj, @@ -2030,8 +2057,13 @@ def processBone( material, specificMat, drawLayer, switchOption.materialOverrideType, texDimensions ) ) - overrideNode.parent = transformNode - transformNode.children.append(overrideNode) + if parentTransformNode: + overrideNode.parent = transformNode + transformNode.children.append(overrideNode) + else: + geolayout.nodes.append(transformNode) + + return materialOverrides def processSwitchBoneMatOverrides(materialOverrides, switchBone): @@ -2147,10 +2179,8 @@ def checkIfFirstNonASMNode(childNode): # they precede them def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parentNode, drawLayer): # Add node to its immediate parent - # print(str(type(parentNode.node)) + str(type(transformNode.node))) transformNode.skinned = True - # print("Skinned mesh exists.") # Get skinned node bone = armatureObj.data.bones[boneName] @@ -2170,7 +2200,7 @@ def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parent acrossSwitchNode = False while highestChildNode.parent is not None and not ( highestChildNode.parent.node.hasDL or highestChildNode.parent.skinnedWithoutDL - ): # empty 0x13 command? + ): isFirstChild &= checkIfFirstNonASMNode(highestChildNode) hasNonDeform0x13Command |= isinstance(highestChildNode.parent.node, DisplayListWithOffsetNode) @@ -2180,12 +2210,9 @@ def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parent highestChildCopyParent = TransformNode(copy.copy(highestChildNode.node)) highestChildCopyParent.children = [highestChildCopy] highestChildCopy.parent = highestChildCopyParent - # print(str(highestChildCopy.node) + " " + str(isFirstChild)) highestChildCopy = highestChildCopyParent - # isFirstChild &= checkIfFirstNonASMNode(highestChildNode) if highestChildNode.parent is None: raise PluginError('Issue with "' + boneName + '": Deform parent bone not found for skinning.') - # raise PluginError("There shouldn't be a skinned mesh section if there is no deform parent. This error may have ocurred if a switch option node is trying to skin to a parent but no deform parent exists.") # Otherwise, remove the transformNode from the parent and # duplicate the node heirarchy up to the last deform parent. @@ -2193,7 +2220,6 @@ def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parent # then add the duplicated node hierarchy afterward. if highestChildNode != transformNode: if not isFirstChild: - # print("Hierarchy but not first child.") if hasNonDeform0x13Command: raise PluginError( "Error with " @@ -2220,7 +2246,7 @@ def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parent precedingFunctionCmds.insert(0, copy.deepcopy(highestChildNode.parent.children[highestChildIndex - 1])) highestChildIndex -= 1 - # _____________ + # add skinned mesh node highestChildCopy.parent = highestChildNode.parent highestChildCopy.parent.children.append(skinnedTransformNode) @@ -2235,21 +2261,41 @@ def addSkinnedMeshNode(armatureObj, boneName, skinnedMesh, transformNode, parent transformNode = transformNodeCopy else: - # print("Hierarchy with first child.") nodeIndex = highestChildNode.parent.children.index(highestChildNode) while nodeIndex > 0 and type(highestChildNode.parent.children[nodeIndex - 1].node) is FunctionNode: nodeIndex -= 1 highestChildNode.parent.children.insert(nodeIndex, skinnedTransformNode) skinnedTransformNode.parent = highestChildNode.parent else: - # print("Immediate child.") - nodeIndex = parentNode.children.index(transformNode) - parentNode.children.insert(nodeIndex, skinnedTransformNode) - skinnedTransformNode.parent = parentNode + # if the skinned mesh is the first child, you can append that DL to that parent + # instead of requiring a new node, because there will be nothing in between them + # to interrupt the skinning + add_skinned_mesh_to_parent_fMesh(skinnedTransformNode, highestChildNode.parent) return transformNode +def add_skinned_mesh_to_parent_fMesh(skinned_transform_node, parent_node): + parent_fMesh = parent_node.node.fMesh + skinned_fMesh = skinned_transform_node.node.fMesh + if not parent_fMesh: + parent_node.node.fMesh = skinned_transform_node.node.fMesh + else: + while SPEndDisplayList() in parent_fMesh.draw.commands: + parent_fMesh.draw.commands.remove(SPEndDisplayList()) + # remove repeat material calls + first_mat_call = 0 + first_mat_index = None + for index, command in enumerate(skinned_fMesh.draw.commands): + if isinstance(command, SPDisplayList) and command.displayList.tag == GfxListTag.Material: + first_mat_call = command + first_mat_index = index + break + if first_mat_call.displayList == parent_fMesh.currentFMaterial.material: + skinned_fMesh.draw.commands.pop(first_mat_index) + parent_fMesh.draw.commands.extend(skinned_fMesh.draw.commands) + + def getAncestorGroups(parentGroup, vertexGroup, armatureObj, obj): if parentGroup is None: return [] @@ -2469,13 +2515,6 @@ def saveModelGivenVertexGroup( ] ) - # Must be done after all geometry saved - for (material, specificMat, overrideType) in materialOverrides: - for drawLayer, fMesh in fMeshes.items(): - saveOverrideDraw(obj, fModel, material, specificMat, overrideType, fMesh, drawLayer, convertTextureData) - for drawLayer, fMesh in fSkinnedMeshes.items(): - saveOverrideDraw(obj, fModel, material, specificMat, overrideType, fMesh, drawLayer, convertTextureData) - return fMeshes, fSkinnedMeshes, usedDrawLayers From 2f736aeefdb8dd787e22ea67c8970873409a9687 Mon Sep 17 00:00:00 2001 From: scut Date: Sat, 8 Jul 2023 10:01:42 -0400 Subject: [PATCH 2/4] removed start nodes from existence unless the user manually puts in node, now all transform nodes simply begin at the geo layout root as god intended --- fast64_internal/sm64/sm64_geolayout_writer.py | 267 ++++++++---------- 1 file changed, 112 insertions(+), 155 deletions(-) diff --git a/fast64_internal/sm64/sm64_geolayout_writer.py b/fast64_internal/sm64/sm64_geolayout_writer.py index fba215231..3ac5c31af 100644 --- a/fast64_internal/sm64/sm64_geolayout_writer.py +++ b/fast64_internal/sm64/sm64_geolayout_writer.py @@ -390,8 +390,6 @@ def convertArmatureToGeolayout( meshGeolayout = geolayoutGraph.startGeolayout for i, startBoneName in enumerate(startBoneNames): - # if i > 0: - # meshGeolayout.nodes.append(TransformNode(StartNode())) materialOverrides = processBone( fModel, startBoneName, @@ -1047,179 +1045,145 @@ def geoWriteTextDump(textDumpFilePath, geolayoutGraph, levelData): # Afterward, the node hierarchy is traversed again, and any SwitchOverride # nodes are converted to actual geolayout node hierarchies. -def generateSwitchOptions(transformNode, geolayout, geolayoutGraph, prefix): - if isinstance(transformNode.node, JumpNode): - for node in transformNode.node.geolayout.nodes: - generateSwitchOptions(node, transformNode.node.geolayout, geolayoutGraph, prefix) +def generateSwitchOptions(transform_node, geolayout, geolayoutGraph, prefix): + if isinstance(transform_node.node, JumpNode): + for node in transform_node.node.geolayout.nodes: + generateSwitchOptions(node, transform_node.node.geolayout, geolayoutGraph, prefix) + overrideNodes = [] - if isinstance(transformNode.node, SwitchNode): - switchName = transformNode.node.name - prefix += "_" + switchName - # prefix = switchName + if isinstance(transform_node.node, SwitchNode): + switchName = transform_node.node.name + prefix = f"{prefix}_{switchName}" materialOverrideTexDimensions = None - i = 0 - while i < len(transformNode.children): - prefixName = prefix + "_opt" + str(i) - childNode = transformNode.children[i] - if isinstance(childNode.node, SwitchOverrideNode): - drawLayer = childNode.node.drawLayer - material = childNode.node.material - specificMat = childNode.node.specificMat - overrideType = childNode.node.overrideType - texDimensions = childNode.node.texDimensions - if ( - texDimensions is not None - and materialOverrideTexDimensions is not None - and materialOverrideTexDimensions != tuple(texDimensions) - ): - raise PluginError( - 'In switch bone "' - + switchName - + '", some material ' - + "overrides \nhave textures with dimensions differing from the original material.\n" - + "UV coordinates are in pixel units, so there will be UV errors in those overrides.\n " - + "Make sure that all overrides have the same texture dimensions as the original material.\n" - + "Note that materials with no textures default to dimensions of 32x32." - ) + for child_index, child_node in enumerate(transform_node.children): + # first child + if not isinstance(child_node.node, SwitchOverrideNode): + continue + + prefix_name = f"{prefix}_opt{child_index}" + child_node_tex_dimensions = child_node.node.texDimensions + if ( + child_node_tex_dimensions is not None + and materialOverrideTexDimensions is not None + and materialOverrideTexDimensions != tuple(child_node_tex_dimensions) + ): + raise PluginError( + 'In switch bone "' + + switchName + + '", some material ' + + "overrides \nhave textures with dimensions differing from the original material.\n" + + "UV coordinates are in pixel units, so there will be UV errors in those overrides.\n " + + "Make sure that all overrides have the same texture dimensions as the original material.\n" + + "Note that materials with no textures default to dimensions of 32x32." + ) - if texDimensions is not None: - materialOverrideTexDimensions = tuple(texDimensions) - - # This should be a 0xB node - # copyNode = duplicateNode(transformNode.children[0], - # transformNode, transformNode.children.index(childNode)) - index = transformNode.children.index(childNode) - transformNode.children.remove(childNode) - - # Switch option bones should have unique names across all - # armatures. - optionGeolayout = geolayoutGraph.addGeolayout(childNode, prefixName) - geolayoutGraph.addJumpNode(transformNode, geolayout, optionGeolayout, index) - optionGeolayout.nodes.append(TransformNode(StartNode())) - copyNode = optionGeolayout.nodes[0] - - # i -= 1 - # Assumes first child is a start node, where option 0 is - # assumes overrideChild starts with a Start node - option0Nodes = [transformNode.children[0]] - if len(option0Nodes) == 1 and isinstance(option0Nodes[0].node, StartNode): - for startChild in option0Nodes[0].children: - generateOverrideHierarchy( - copyNode, - startChild, - material, - specificMat, - overrideType, - drawLayer, - option0Nodes[0].children.index(startChild), - optionGeolayout, - geolayoutGraph, - optionGeolayout.name, - ) - else: - for overrideChild in option0Nodes: - generateOverrideHierarchy( - copyNode, - overrideChild, - material, - specificMat, - overrideType, - drawLayer, - option0Nodes.index(overrideChild), - optionGeolayout, - geolayoutGraph, - optionGeolayout.name, - ) - if material is not None: - overrideNodes.append(copyNode) - i += 1 - for i in range(len(transformNode.children)): - childNode = transformNode.children[i] - if isinstance(transformNode.node, SwitchNode): - prefixName = prefix + "_opt" + str(i) + if child_node_tex_dimensions is not None: + materialOverrideTexDimensions = tuple(child_node_tex_dimensions) + + # Switch option bones should have unique names across all armatures. + transform_node.children.remove(child_node) # remove child node aka switch override node + option_geo_layout = geolayoutGraph.addGeolayout(child_node, prefix_name) # add geo layout starting from child node + geolayoutGraph.addJumpNode(transform_node, geolayout, option_geo_layout, child_index) # replace switch override with jump node to override GL + + # for switch overrides, each one is a copy of the first child, which is the default option, so iterate the first childs + # hierarchy and create a copy of that and place it in the option_geo_layout + generateOverrideHierarchy( + None, + transform_node.children[0], + child_node.node.material, + child_node.node.specificMat, + child_node.node.overrideType, + child_node.node.drawLayer, + 0, + option_geo_layout, + geolayoutGraph, + option_geo_layout.name, + ) + + # if this is a material override, add to the list + # if child_node.node.material is not None: + # overrideNodes.append(optionGeolayout.nodes[0]) + + for i, child_node in enumerate(transform_node.children): + if isinstance(transform_node.node, SwitchNode): + prefix_name = f"{prefix}_opt{i}" else: - prefixName = prefix + prefix_name = prefix - if childNode not in overrideNodes: - generateSwitchOptions(childNode, geolayout, geolayoutGraph, prefixName) + if child_node not in overrideNodes: + generateSwitchOptions(child_node, geolayout, geolayoutGraph, prefix_name) def generateOverrideHierarchy( - parentCopyNode, - transformNode, + parent_node, + transform_node, material, specificMat, overrideType, drawLayer, index, geolayout, - geolayoutGraph, + geolayout_graph, switchOptionName, ): - # print(transformNode.node) - if isinstance(transformNode.node, SwitchOverrideNode) and material is not None: + if isinstance(transform_node.node, SwitchOverrideNode) and material is not None: return - copyNode = TransformNode(copy.copy(transformNode.node)) - copyNode.parent = parentCopyNode - parentCopyNode.children.insert(index, copyNode) - if isinstance(transformNode.node, JumpNode): - jumpName = switchOptionName + "_jump_" + transformNode.node.geolayout.name - jumpGeolayout = geolayoutGraph.addGeolayout(transformNode, jumpName) - oldGeolayout = copyNode.node.geolayout - copyNode.node.geolayout = jumpGeolayout - geolayoutGraph.addGeolayoutCall(geolayout, jumpGeolayout) - startNode = TransformNode(StartNode()) - jumpGeolayout.nodes.append(startNode) - if len(oldGeolayout.nodes) == 1 and isinstance(oldGeolayout.nodes[0].node, StartNode): - for node in oldGeolayout.nodes[0].children: - generateOverrideHierarchy( - startNode, - node, - material, - specificMat, - overrideType, - drawLayer, - oldGeolayout.nodes[0].children.index(node), - jumpGeolayout, - geolayoutGraph, - jumpName, - ) - else: - for node in oldGeolayout.nodes: - generateOverrideHierarchy( - startNode, - node, - material, - specificMat, - overrideType, - drawLayer, - oldGeolayout.nodes.index(node), - jumpGeolayout, - geolayoutGraph, - jumpName, - ) - - elif not isinstance(copyNode.node, SwitchOverrideNode) and copyNode.node.hasDL: + # copy the node hierarchy, append transform_node to root if no parent + if parent_node: + copy_node = TransformNode(copy.copy(transform_node.node)) + copy_node.parent = parent_node + parent_node.children.insert(index, copy_node) + else: + copy_node = TransformNode(copy.copy(transform_node.node)) + geolayout.nodes.append(copy_node) + + # if you have a jump node, create a full copy by parsing through that geo layout + if isinstance(transform_node.node, JumpNode): + jump_name = f"{switchOptionName}_jump_{transform_node.node.geolayout.name}" + jump_geo_layout = geolayout_graph.addGeolayout(transform_node, jump_name) + original_geo_layout = copy_node.node.geolayout + copy_node.node.geolayout = jump_geo_layout + geolayout_graph.addGeolayoutCall(geolayout, jump_geo_layout) + + # iterate starting with the first nodes children + for index, node in enumerate(original_geo_layout.nodes): + print("jump geo", type(node.node)) + generateOverrideHierarchy( + None, + node, + material, + specificMat, + overrideType, + drawLayer, + index, + jump_geo_layout, + geolayout_graph, + jump_name, + ) + + # replace the DL with the override DL + elif not isinstance(copy_node.node, SwitchOverrideNode) and copy_node.node.hasDL: if material is not None: - copyNode.node.DLmicrocode = copyNode.node.fMesh.drawMatOverrides[(material, specificMat, overrideType)] - copyNode.node.override_hash = (material, specificMat, overrideType) + copy_node.node.DLmicrocode = copy_node.node.fMesh.drawMatOverrides[(material, specificMat, overrideType)] + copy_node.node.override_hash = (material, specificMat, overrideType) if drawLayer is not None: - copyNode.node.drawLayer = drawLayer + copy_node.node.drawLayer = drawLayer - for child in transformNode.children: + # recurse + for index, child in enumerate(transform_node.children): generateOverrideHierarchy( - copyNode, + copy_node, child, material, specificMat, overrideType, drawLayer, - transformNode.children.index(child), + index, geolayout, - geolayoutGraph, + geolayout_graph, switchOptionName, ) @@ -1925,10 +1889,7 @@ def processBone( # see generateSwitchOptions() for explanation. else: if len(bone.children) > 0: - # nextStartNode = None - nextStartNode = TransformNode(StartNode()) - transformNode.children.append(nextStartNode) - nextStartNode.parent = transformNode + nextStartNode = transformNode childrenNames = sorted([bone.name for bone in bone.children]) for name in childrenNames: @@ -1989,7 +1950,6 @@ def processBone( optionGeolayout.nodes.append(startNode) else: startNode = switchIndex - # startNode = TransformNode(StartNode()) childrenNames = sorted([bone.name for bone in optionBone.children]) for name in childrenNames: @@ -2057,11 +2017,8 @@ def processBone( material, specificMat, drawLayer, switchOption.materialOverrideType, texDimensions ) ) - if parentTransformNode: - overrideNode.parent = transformNode - transformNode.children.append(overrideNode) - else: - geolayout.nodes.append(transformNode) + overrideNode.parent = transformNode + transformNode.children.append(overrideNode) return materialOverrides From f362247c792aa6d582b81cd0962059dbe2f6866a Mon Sep 17 00:00:00 2001 From: scut Date: Wed, 1 Jan 2025 11:08:22 -0500 Subject: [PATCH 3/4] formatting changes per PR review --- fast64_internal/sm64/sm64_geolayout_writer.py | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/fast64_internal/sm64/sm64_geolayout_writer.py b/fast64_internal/sm64/sm64_geolayout_writer.py index e4f6915f4..277306a03 100644 --- a/fast64_internal/sm64/sm64_geolayout_writer.py +++ b/fast64_internal/sm64/sm64_geolayout_writer.py @@ -437,14 +437,14 @@ def convertArmatureToGeolayout(armatureObj, obj, convertTransformMatrix, camera, convertTextureData, ) - def walk(node, fMeshes): + def walk(node: TransformNode, fMeshes: dict[int, FMesh]): base_node = node.node - if type(base_node) == JumpNode: - if base_node.geolayout: + if isinstance(base_node, JumpNode): + if base_node.geolayout is not None: for node in base_node.geolayout.nodes: fMeshes = walk(node, fMeshes) fMesh = getattr(base_node, "fMesh", None) - if fMesh: + if fMesh is not None: if fMeshes.get(base_node.drawLayer, None): fMeshes[base_node.drawLayer].append(fMesh) else: @@ -1120,10 +1120,6 @@ def generateSwitchOptions(transform_node, geolayout, geolayoutGraph, prefix): option_geo_layout.name, ) - # if this is a material override, add to the list - # if child_node.node.material is not None: - # overrideNodes.append(optionGeolayout.nodes[0]) - for i, child_node in enumerate(transform_node.children): if isinstance(transform_node.node, SwitchNode): prefix_name = f"{prefix}_opt{i}" @@ -1663,7 +1659,7 @@ def processBone( # true when this is the start of the geo layout # if there is no parent, then instead set the node to be the root of our geo layout - if type(parentTransformNode) == int: + if isinstance(parentTransformNode, int): if len(geolayout.nodes) > parentTransformNode: parentTransformNode = geolayout.nodes[parentTransformNode] else: @@ -1681,7 +1677,7 @@ def processBone( if not zeroRotation: node = DisplayListWithOffsetNode(int(bone.draw_layer), hasDL, mathutils.Vector((0, 0, 0))) - if parentTransformNode: + if parentTransformNode is not None: parentTransformNode = addParentNode( parentTransformNode, TranslateRotateNode(1, 0, False, translate, rotate) ) @@ -1810,7 +1806,7 @@ def processBone( if usedDrawLayers is not None: lastDeformName = boneName - if parentTransformNode: + if parentTransformNode is not None: parentTransformNode.children.append(transformNode) transformNode.parent = parentTransformNode else: @@ -1842,7 +1838,7 @@ def processBone( node.DLmicrocode = fMesh.draw node.fMesh = fMesh # Used for material override switches - if parentTransformNode: + if parentTransformNode is not None: parentTransformNode.children.append(transformNode) transformNode.parent = parentTransformNode else: @@ -1868,7 +1864,7 @@ def processBone( additionalTransformNode.parent = transformNode else: - if parentTransformNode: + if parentTransformNode is not None: parentTransformNode.children.append(transformNode) transformNode.parent = parentTransformNode else: From 3093c709655f7e7fb1c37aea2905e53e602e2940 Mon Sep 17 00:00:00 2001 From: Scut <6765126+jesusyoshi54@users.noreply.github.com> Date: Tue, 22 Apr 2025 20:47:53 -0400 Subject: [PATCH 4/4] Update fast64_internal/sm64/sm64_geolayout_writer.py Co-authored-by: Lila --- fast64_internal/sm64/sm64_geolayout_writer.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fast64_internal/sm64/sm64_geolayout_writer.py b/fast64_internal/sm64/sm64_geolayout_writer.py index 277306a03..ba7c73628 100644 --- a/fast64_internal/sm64/sm64_geolayout_writer.py +++ b/fast64_internal/sm64/sm64_geolayout_writer.py @@ -1677,12 +1677,12 @@ def processBone( if not zeroRotation: node = DisplayListWithOffsetNode(int(bone.draw_layer), hasDL, mathutils.Vector((0, 0, 0))) - if parentTransformNode is not None: - parentTransformNode = addParentNode( - parentTransformNode, TranslateRotateNode(1, 0, False, translate, rotate) - ) + trans_rotate_node = TranslateRotateNode(1, 0, False, translate, rotate) + if parentTransformNode is None: + parentTransformNode = TransformNode(trans_rotate_node) + geolayout.nodes.append(parentTransformNode) else: - geolayout.nodes.append(TranslateRotateNode(1, 0, False, translate, rotate)) + parentTransformNode = addParentNode(parentTransformNode, trans_rotate_node) lastTranslateName = boneName lastRotateName = boneName