-
Notifications
You must be signed in to change notification settings - Fork 283
Implement Prefab workflow
#776
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
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
d5eb55b
feat(editor): add dedicated .ovprefab file type and icon support
Gopmyc dd27e04
feat(editor): add prefab save/instantiate workflow and retargeting
Gopmyc 64e7e4e
feat(prefab): track source instances and add apply/revert actions
Gopmyc c813f15
feat(editor): add prefab creation entry and hierarchy prefab controls
Gopmyc e045801
feat(icon) : Improve `Prefab` icon
Gopmyc 6914c1b
Fix prefab context actions and nested prefab source remapping
Gopmyc 3fc9291
Harden hierarchy prefab menu target resolution
Gopmyc 06cb33e
Fix nested prefab source normalization and root resolution
Gopmyc d31b29f
Inline prefab instantiation guard logging on early returns
Gopmyc 8823405
Inline prefab guard log-and-return in editor actions
Gopmyc 655c1fb
Adjust prefab open behavior and default save filename
Gopmyc 65361e3
Improve prefab instance workflows and actor-to-folder prefab drop
Gopmyc 9b0f508
Refine prefab instantiation guard logging and compact single-line ifs
Gopmyc e8aa20c
Fix MSVC PDB contention by enabling /FS in premake
Gopmyc 6e47f8d
fix(editor): keep prefab instance identity when reverting
Gopmyc fb1ee23
refactor(core): move prefab operations out of editor module
Gopmyc d05bfd1
fix(editor): restore contextual actions after scene reload
Gopmyc 49d739d
feat(core): add prefab node GUID metadata for actor instances
Gopmyc 50dcef4
refactor(editor): simplify hierarchy context target and actor creatio…
Gopmyc faa4b69
fix(editor): match prefab revert nodes by prefab GUID metadata
Gopmyc f253e46
fix(prefab): remap revert actor refs with serialized prefab GUIDs
Gopmyc 5357328
fix(editor): guard context actor pointers in hierarchy menus
Gopmyc c953e90
chore(editor): remove non-essential prefab apply/revert info logs
Gopmyc 4f4b606
Merge remote-tracking branch 'origin/main' into 25-beta
Gopmyc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
Sources/OvCore/include/OvCore/SceneSystem/PrefabOperations.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /** | ||
| * @project: Overload | ||
| * @author: Overload Tech. | ||
| * @licence: MIT | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <filesystem> | ||
| #include <functional> | ||
|
|
||
| namespace OvCore::ECS | ||
| { | ||
| class Actor; | ||
| } | ||
|
|
||
| namespace OvCore::SceneSystem | ||
| { | ||
| /** | ||
| * Utility functions to serialize and instantiate prefab files. | ||
| */ | ||
| class PrefabOperations | ||
| { | ||
| public: | ||
| /** | ||
| * Disabled constructor | ||
| */ | ||
| PrefabOperations() = delete; | ||
|
|
||
| /** | ||
| * Save an actor hierarchy to a prefab file. | ||
| * @param p_rootActor | ||
| * @param p_outputPath | ||
| */ | ||
| static bool SaveToFile(OvCore::ECS::Actor& p_rootActor, const std::filesystem::path& p_outputPath); | ||
|
|
||
| /** | ||
| * Instantiate a prefab file using the provided actor factory. | ||
| * @param p_prefabPath | ||
| * @param p_createActor | ||
| */ | ||
| static OvCore::ECS::Actor* InstantiateFromFile( | ||
| const std::filesystem::path& p_prefabPath, | ||
| const std::function<OvCore::ECS::Actor&(void)>& p_createActor | ||
| ); | ||
| }; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
Sources/OvCore/src/OvCore/SceneSystem/PrefabOperations.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| /** | ||
| * @project: Overload | ||
| * @author: Overload Tech. | ||
| * @licence: MIT | ||
| */ | ||
|
|
||
| #include <cstdint> | ||
| #include <string> | ||
| #include <unordered_map> | ||
| #include <vector> | ||
|
|
||
| #include <tinyxml2.h> | ||
|
|
||
| #include <OvDebug/Logger.h> | ||
| #include <OvCore/ECS/Actor.h> | ||
| #include <OvCore/SceneSystem/PrefabOperations.h> | ||
|
|
||
| namespace | ||
| { | ||
| void SerializeActorHierarchy( | ||
| OvCore::ECS::Actor& p_actor, | ||
| tinyxml2::XMLDocument& p_doc, | ||
| tinyxml2::XMLNode& p_actorsRoot) | ||
| { | ||
| if (!p_actor.HasPrefabNodeGUID()) | ||
| { | ||
| p_actor.SetPrefabNodeGUID(p_actor.GetGUID()); | ||
| } | ||
|
|
||
| p_actor.OnSerialize(p_doc, &p_actorsRoot); | ||
|
|
||
| for (auto* child : p_actor.GetChildren()) | ||
| { | ||
| SerializeActorHierarchy(*child, p_doc, p_actorsRoot); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| bool OvCore::SceneSystem::PrefabOperations::SaveToFile(OvCore::ECS::Actor& p_rootActor, const std::filesystem::path& p_outputPath) | ||
| { | ||
| tinyxml2::XMLDocument doc; | ||
|
|
||
| auto* rootNode = doc.NewElement("root"); | ||
| doc.InsertFirstChild(rootNode); | ||
|
|
||
| auto* prefabNode = doc.NewElement("prefab"); | ||
| rootNode->InsertEndChild(prefabNode); | ||
|
|
||
| auto* actorsNode = doc.NewElement("actors"); | ||
| prefabNode->InsertEndChild(actorsNode); | ||
|
|
||
| SerializeActorHierarchy(p_rootActor, doc, *actorsNode); | ||
|
|
||
| return doc.SaveFile(p_outputPath.string().c_str()) == tinyxml2::XML_SUCCESS; | ||
| } | ||
|
|
||
| OvCore::ECS::Actor* OvCore::SceneSystem::PrefabOperations::InstantiateFromFile( | ||
| const std::filesystem::path& p_prefabPath, | ||
| const std::function<OvCore::ECS::Actor&(void)>& p_createActor) | ||
| { | ||
| if (!p_createActor) | ||
| { | ||
| OVLOG_ERROR("Failed to instantiate prefab \"" + p_prefabPath.string() + "\": invalid actor factory callback."); | ||
| return nullptr; | ||
| } | ||
|
|
||
| tinyxml2::XMLDocument doc; | ||
| const auto loadResult = doc.LoadFile(p_prefabPath.string().c_str()); | ||
| if (loadResult != tinyxml2::XML_SUCCESS) | ||
| { | ||
| OVLOG_ERROR("Failed to instantiate prefab \"" + p_prefabPath.string() + "\": XML parsing failed (code " + std::to_string(loadResult) + ")."); | ||
| return nullptr; | ||
| } | ||
|
|
||
| auto* rootNode = doc.FirstChildElement("root"); | ||
| auto* prefabNode = rootNode ? rootNode->FirstChildElement("prefab") : nullptr; | ||
| auto* actorsNode = prefabNode ? prefabNode->FirstChildElement("actors") : nullptr; | ||
|
|
||
| if (!actorsNode) | ||
| { | ||
| OVLOG_ERROR("Failed to instantiate prefab \"" + p_prefabPath.string() + "\": missing <root>/<prefab>/<actors> node."); | ||
| return nullptr; | ||
| } | ||
|
|
||
| struct PendingAttachment | ||
| { | ||
| OvCore::ECS::Actor* actor = nullptr; | ||
| int64_t sourceParentID = 0; | ||
| }; | ||
|
|
||
| std::vector<PendingAttachment> pendingAttachments; | ||
| std::unordered_map<int64_t, OvCore::ECS::Actor*> sourceToInstance; | ||
|
|
||
| for (auto* currentActor = actorsNode->FirstChildElement("actor"); | ||
| currentActor; | ||
| currentActor = currentActor->NextSiblingElement("actor")) | ||
| { | ||
| auto& newActor = p_createActor(); | ||
| const int64_t generatedID = newActor.GetID(); | ||
| const uint64_t generatedGUID = newActor.GetGUID(); | ||
|
|
||
| newActor.OnDeserialize(doc, currentActor); | ||
| const uint64_t prefabNodeGUID = newActor.HasPrefabNodeGUID() ? newActor.GetPrefabNodeGUID() : newActor.GetGUID(); | ||
| newActor.SetPrefabNodeGUID(prefabNodeGUID); | ||
|
|
||
| pendingAttachments.push_back({ | ||
| &newActor, | ||
| newActor.GetParentID() | ||
| }); | ||
|
|
||
| sourceToInstance[newActor.GetID()] = &newActor; | ||
|
|
||
| newActor.SetID(generatedID); | ||
| newActor.SetGUID(generatedGUID); | ||
| } | ||
|
|
||
| OvCore::ECS::Actor* instantiatedRoot = nullptr; | ||
|
|
||
| for (auto& pending : pendingAttachments) | ||
| { | ||
| if (auto found = sourceToInstance.find(pending.sourceParentID); found != sourceToInstance.end()) | ||
| { | ||
| pending.actor->SetParent(*found->second); | ||
| } | ||
| else if (!instantiatedRoot) | ||
| { | ||
| instantiatedRoot = pending.actor; | ||
| } | ||
| } | ||
|
|
||
| return instantiatedRoot; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| #pragma once | ||
|
|
||
| #include <functional> | ||
| #include <optional> | ||
|
|
||
| namespace OvUI::Widgets::Menu | ||
| { | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.