-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[OoT] New Exporter #256
base: main
Are you sure you want to change the base?
[OoT] New Exporter #256
Conversation
This should be ready to review now, I don't think I'm gonna add something else (it's already huge sorry) I decided to keep the checkbox I made to toggle between the two versions, I simply commented the lines, this is on purpose and will be removed with the old version (I can remove that once the review is done and ready to merge of course) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I like the organization into more smaller modular parts, but I have a couple issues. Note that I mostly skimmed through the PR, I didn't test it for correctness yet but mostly just for code organization. I didn't mark all of the spots where the following comments apply, just some of them. I'm also a little rusty on OOT stuff so let me know if some of the comments are wrong.
- A lot of the classes marked with
@dataclass
shouldn't be dataclasses at all, assuming they're marked as such in order to handle automatic__init__()
generation. A lot of init-related temporary state is unnecessarily stored as variables, and a lot of derived members are given optional values (where they shouldn't be) in order to "hide" them from being needed in the__init__()
. The use of__post_init__()
seems to be a workaround to getting derived state, but at that point its much more clear to just define an__init__()
function that only takes in the necessary arguments. - A couple classes are just collections of static methods - they should just be functions imported from a separate file, or the methods should be marked
@staticmethod
to avoid class instantiation. For example:
from . import spec
...
spec.editSpec(self.exporter)
isRoomTransition: Optional[bool] = None | ||
roomFrom: Optional[int] = None | ||
roomTo: Optional[int] = None | ||
cameraFront: Optional[str] = None | ||
cameraBack: Optional[str] = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should not be optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's weird but I'd like to keep this initialised to None
so if there's any uncaught/unknown issue it would make it more obvious what the issue is, and just using Optional
since I was told thing: str = None
is bad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be easier to catch errors at construction time of the TransitionActor
instead of letting this continue on with invalid state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I can consider this as solved too (field(init=False)
), the members are set in the same function as the one that calls this class in the first place (which is SceneTransitionActors
's post init)
fast64_internal/oot/exporter/base.py
Outdated
|
||
|
||
@dataclass | ||
class Base: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be converted to a file with imported functions or a class with static methods that can be used by other classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed it "Utility", let me know if you think of a better name (and I used static methods)
Fwiw I don't know the pythonic way to have "dataclasses but some of the fields will be initialized later" I'll try to look it up |
(just in case I forget: https://discord.com/channels/874816709855440926/874819026629574717/1200770808927244499) |
Also, I'm a bit confused about the overall file organization at this point - is the new |
for now they will stay because it would make this PR way too big (and painful for conflicts) but I want to remove everything called when you use and of course I will remove the related files to the non-scene exporters I implemented |
In regards to optional arguments and overriding (#256 (comment)), what I meant is that someone could write the code I think there's a discrepancy about how we're looking at dataclasses. From what I'm understanding, dataclasses are supposed to be for classes that are primarily for storing state. Using it for the f3d command classes makes sense in that case, as those only really store state and are operated on by other functions/classes. However, in a lot of cases the export dataclasses have the export functionality embedded in them, which leads to a lot of questionable design decisions.
I think a good middle ground would be a solution like this: https://stackoverflow.com/a/72519184. Basically, the dataclass doesn't use any |
Also, are all the cutscene commands defined twice in different files but with identical definitions? |
I wanna do this change in two rounds (or more if needed), round 1 the refactored exporter (this PR), round 2 remove all of the unused code and if that's too long round 3 adapt the remaining cutscene stuff to this, which is the cutscene importer So yea I know it's not ideal but I'm concerned about PR sizes |
so basically you want me to revert the 1 hour and a half-ish of work I did yesterday to use it seems to me it's down to what we want in the codebase and not what Python tells us to do, I'm just tired of changing the ~50 different classes this PR adds + testing everything works, fixing issues etc, I usually spent a whole day doing everything and I just wanna move on something else at this point, and I already spent a lot of time working on this (since september, so like 5 months) btw the whole point of this system is:
and I feel what you want just breaks this entirely idk, it makes me feel like all of the time I spent on this was basically for nothing lol I'd like to hear what @Dragorn421 thinks of this and if he got other ideas for a solution before doing anything else, I don't wanna do lots of changes again if it turns out it wasn't necessary |
I'm sorry about the extra work, but I did state that I thought |
I'll try to do the changes soon, I think it's dumb that my own opinions are blocking this cool thing |
This is something I wanted to do for a while, it should work properly according to my tests (thanks again to Richie for that)
This relies on dataclasses, I don't think it's the best thing for performances but at least it makes the code easy to follow imo, also it includes functions to get C data so it's kinda 2 in 1, this makes you able to call one of the classes to export a specific type of data, I did that for cutscenes and collisions (collisions required more changes but cutscenes are a one-line change)
Anyway this was fun to make!
Any feedback/suggestions is appreciated! (the diff is huge but this doesn't edit a lot of the original files, most of the diff comes from new files I created)
Extra note: this fix the known issues related to waterbox duplicates, paths and the file(s) being inconsistent at export time, for instance actor entries swapping in the actor list for no reasons
This exporter has everything in the same place (inside the
exporter
folder) instead of having bits of export scattered here and there, I think it makes more sense like this