Skip to content

Commit

Permalink
[OoT] OoT Object changes & small changes/fixes/removals (#95)
Browse files Browse the repository at this point in the history
* Use XML for Object List

* Deleted ``oot_parse.py`` as it's not used anymore

* Replaced ``\t`` by ``indent`` from ``oot_utility``

* add defines for actor and object lists lengths

* Add missing objects when exporting, fixed scene obj selected, removed ``drawParentSceneRoom`` as it's unused

* removed another unused file

* removed undefines

* obj_gameplay_XXX check fix when adding missing objects

* check if ObjectKey is None

* review part 1

* actor list name update

* upgrade objects from old blends (review part 2)

* removed defines from header

* black formatting

* bug fix + black

* ``.format`` -> f-string
updated ActorList.xml

* OoT Data system

* revert formatting on unmodified files

* revert unwanted changes

* enhancements

* review

* review 2

* review 3

* review 4

* black

* add back ID in objects names,
add custom object id to object name for custom objects

* review 5

* suggestions and fixed the actor xml

* small issue fix

* fixed typo

* small detail

* review 6

* fixed v5 merge unwanted change,
use ``ootGetSceneOrRoomHeader`` for ``addMissingObjectToProp``

* set version when adding something

* fixed some object having the wrong name

* fixed upgrade and adding object to prop issues

* split object funcs to their own files

* black

* annotations

* ran black on (already formatted) modified files

* review 7

* review 7.1

* review 8

* review + bugfix

* review 10

* explained in a comment why checking actorID none

* improved upgrade system

* fixed object list import
  • Loading branch information
Yanis42 authored Nov 17, 2022
1 parent c1de4bb commit 925df1a
Show file tree
Hide file tree
Showing 26 changed files with 4,592 additions and 1,084 deletions.
1 change: 1 addition & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ def upgrade_changed_props():
"""Set scene properties after a scene loads, used for migrating old properties"""
SM64_Properties.upgrade_changed_props()
SM64_ObjectProperties.upgrade_changed_props()
OOT_ObjectProperties.upgrade_changed_props()


def upgrade_scene_props_node():
Expand Down
48 changes: 48 additions & 0 deletions fast64_internal/oot/data/oot_actor_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from os import path
from dataclasses import dataclass
from .oot_getters import getXMLRoot
from .oot_data import OoT_BaseElement


@dataclass
class OoT_ActorElement(OoT_BaseElement):
category: str
tiedObjects: list[str]


class OoT_ActorData:
"""Everything related to OoT Actors"""

def __init__(self):
# Path to the ``ActorList.xml`` file
actorXML = path.dirname(path.abspath(__file__)) + "/xml/ActorList.xml"
actorRoot = getXMLRoot(actorXML)

# general actor list
self.actorList: list[OoT_ActorElement] = []

for actor in actorRoot.iterfind("Actor"):
tiedObjects = []
objKey = actor.get("ObjectKey")
actorName = f"{actor.attrib['Name']} - {actor.attrib['ID'].removeprefix('ACTOR_')}"
if objKey is not None: # actors don't always use an object
tiedObjects = objKey.split(",")
self.actorList.append(
OoT_ActorElement(
actor.attrib["ID"],
actor.attrib["Key"],
actorName,
int(actor.attrib["Index"]),
actor.attrib["Category"],
tiedObjects,
)
)
self.actorsByKey = {actor.key: actor for actor in self.actorList}
self.actorsByID = {actor.id: actor for actor in self.actorList}

# list of tuples used by Blender's enum properties
lastIndex = max(1, *(actor.index for actor in self.actorList))
self.ootEnumActorID = [("None", f"{i} (Deleted from the XML)", "None") for i in range(lastIndex)]
self.ootEnumActorID.insert(0, ("Custom", "Custom Actor", "Custom"))
for actor in self.actorList:
self.ootEnumActorID[actor.index] = (actor.id, actor.name, actor.id)
21 changes: 21 additions & 0 deletions fast64_internal/oot/data/oot_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from dataclasses import dataclass


@dataclass
class OoT_BaseElement:
id: str
key: str
name: str
index: int


@dataclass
class OoT_Data:
"""Contains data related to OoT, like actors or objects"""

def __init__(self):
from .oot_object_data import OoT_ObjectData
from .oot_actor_data import OoT_ActorData

self.objectData = OoT_ObjectData()
self.actorData = OoT_ActorData()
11 changes: 11 additions & 0 deletions fast64_internal/oot/data/oot_getters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from xml.etree.ElementTree import parse as parseXML, Element


def getXMLRoot(xmlPath: str) -> Element:
"""Parse an XML file and return its root element"""
try:
return parseXML(xmlPath).getroot()
except:
from ...utility import PluginError

raise PluginError(f"ERROR: File '{xmlPath}' is missing or malformed.")
55 changes: 55 additions & 0 deletions fast64_internal/oot/data/oot_object_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from dataclasses import dataclass
from os import path
from ...utility import PluginError
from .oot_getters import getXMLRoot
from .oot_data import OoT_BaseElement

# Note: "object" in this context refers to an OoT Object file (like ``gameplay_keep``)


@dataclass
class OoT_ObjectElement(OoT_BaseElement):
pass


class OoT_ObjectData:
"""Everything related to OoT objects"""

def __init__(self):
# general object list
self.objectList: list[OoT_ObjectElement] = []

# Path to the ``ObjectList.xml`` file
objectXML = path.dirname(path.abspath(__file__)) + "/xml/ObjectList.xml"
objectRoot = getXMLRoot(objectXML)

for obj in objectRoot.iterfind("Object"):
objName = f"{obj.attrib['Name']} - {obj.attrib['ID'].removeprefix('OBJECT_')}"
self.objectList.append(
OoT_ObjectElement(obj.attrib["ID"], obj.attrib["Key"], objName, int(obj.attrib["Index"]))
)

self.objectsByID = {obj.id: obj for obj in self.objectList}
self.objectsByKey = {obj.key: obj for obj in self.objectList}

# list of tuples used by Blender's enum properties
self.deletedEntry = ("None", "(Deleted from the XML)", "None")
lastIndex = max(1, *(obj.index for obj in self.objectList))
self.ootEnumObjectKey = self.getObjectIDList(lastIndex + 1, False)

# create the legacy object list for old blends
self.ootEnumObjectIDLegacy = self.getObjectIDList(self.objectsByKey["obj_timeblock"].index + 1, True)

# validate the legacy list, if there's any None element then something's wrong
if self.deletedEntry in self.ootEnumObjectIDLegacy:
raise PluginError("ERROR: Legacy Object List doesn't match!")

def getObjectIDList(self, max: int, isLegacy: bool):
"""Generates and returns the object list in the right order"""
objList = [self.deletedEntry] * max
for obj in self.objectList:
if obj.index < max:
identifier = obj.id if isLegacy else obj.key
objList[obj.index] = (identifier, obj.name, obj.id)
objList[0] = ("Custom", "Custom Object", "Custom")
return objList
Loading

0 comments on commit 925df1a

Please sign in to comment.