Fast-64 / fast64

Blender based editor for scenes, meshes, and more in first-party N64 games
GNU General Public License v3.0
317 stars 73 forks source link

[OoT] when exporting a scene that is already in spec, the segments are moved to the end #403

Open Dragorn421 opened 3 months ago

Dragorn421 commented 3 months ago

for example if the spec contains

// ... the scene and rooms segments for mymap1...

// ... the scene and rooms segments for mymap2...

and that I export mymap1, the previous mymap1 segments will be removed and added to another place than they were previously (the end of the spec):

// ... the scene and rooms segments for mymap2...

// ... the scene and rooms segments for mymap1...

This is very annoying with version control (git), causing diffs like

-// ... the scene and rooms segments for mymap1...
-
 // ... the scene and rooms segments for mymap2...
+
+// ... the scene and rooms segments for mymap1...

I have a patch to solve this but it's kind of bad code as it duplicates logic from other functions:

diff --git a/fast64_internal/oot/exporter/decomp_edit/spec.py b/fast64_internal/oot/exporter/decomp_edit/spec.py
index 2bc05317..42126aca 100644
--- a/fast64_internal/oot/exporter/decomp_edit/spec.py
+++ b/fast64_internal/oot/exporter/decomp_edit/spec.py
@@ -235,6 +235,29 @@ class SpecUtility:
         # get the scene and current segment name and remove the scene
         sceneName = exportInfo.name
         sceneSegmentName = f"{sceneName}_scene"
+
+        sceneSegment_specSection = None
+        sceneSegment_specSectionEntryIndex = None
+        for section in specFile.sections:
+            for entryIndex, entry in enumerate(section.entries):
+                if entry.get_name() == sceneSegmentName or re.match(
+                    f"^{sceneSegmentName}\_room\_[0-9]+$", entry.get_name()
+                ):
+                    sceneSegment_specSection = section
+                    sceneSegment_specSectionEntryIndex = entryIndex
+        if sceneSegment_specSection is None:
+
+            def spec_add_entry(entry: SpecEntry):
+                specFile.append(entry)
+
+        else:
+            segmentsInsertIndex = sceneSegment_specSectionEntryIndex
+
+            def spec_add_entry(entry: SpecEntry):
+                nonlocal segmentsInsertIndex
+                sceneSegment_specSection.entries.insert(segmentsInsertIndex, entry)
+                segmentsInsertIndex += 1
+
         SpecUtility.remove_segments_from_spec(specFile, exportInfo.name)

         assert build_directory is not None
@@ -270,7 +293,7 @@ class SpecUtility:
                     sceneCmds.append(SpecCommand("include", f'"{includeDir}/{sceneSegmentName}_cs_{i}.o"'))

         sceneCmds.append(SpecCommand("number", "2"))
-        specFile.append(SpecEntry(sceneCmds))
+        spec_add_entry(SpecEntry(sceneCmds))

         # rooms
         for i in range(roomTotal):
@@ -294,7 +317,7 @@ class SpecUtility:
                 )

             roomCmds.append(SpecCommand("number", "3"))
-            specFile.append(SpecEntry(roomCmds))
+            spec_add_entry(SpecEntry(roomCmds))

         # finally, write the spec file
         writeFile(exportPath, specFile.to_c())