#pragma once #include "EditorCore.hpp" #include "GameObject.hpp" #include #include #include #include #include // Forward declarations class Level; class LevelManager; /// Represents a seralized GameObject tree. class Level : public RefCounted { friend class LevelManager; private: struct InstanciationEntry; LevelManager* mMan; Uid mUid; std::vector mEntries; public: Level(); ~Level(); void Instanciate(GameObject* relRoot) const; LevelManager* GetLinkedLevelManager() const { return mMan; } const Uid& GetUid() const { return mUid; } // Editor stuff void ShowInstanciationEntries(IEditor& editor); }; class LevelManager { public: static inline LevelManager* instance = nullptr; public: // NOTE: public for the editor; actual game components should not modify the map using this // TODO maybe cut this struct to only the first RcPtr field in release mode? struct LoadableObject { RcPtr level; // TODO make weak pointer std::filesystem::path filePath; // NOTE: these fields are only loaded in dev mode std::string name; std::string description; // Editor book keeping fields bool edited = false; }; // We want pointer stability here for the editor (inspector object) robin_hood::unordered_node_map mObjByUid; public: void DiscoverFilesDesignatedLocation(); void DiscoverFiles(const std::filesystem::path& dir); Level* FindLevel(const Uid& uid) const; /// Get or load the given level Level* LoadLevel(const Uid& uid); /// Send the given level to be loaded on another thread void PrepareLevel(const Uid& uid); /// Create and add a new level object with the given uid. /// Should only be used by the editor. LoadableObject& AddLevel(const Uid& uid); /// Should only be used by the editor. void SaveLevel(const Uid& uid) const; /// Should only be used by the editor. void SaveLevel(const Uid& uid, const std::filesystem::path& path) const; private: void SaveLevelImpl(const LoadableObject& obj, const std::filesystem::path& path) const; }; class LevelWrapperObject : public GameObject { private: RcPtr mLevel; public: LevelWrapperObject(GameWorld* world); ~LevelWrapperObject() override; Level* GetBoundLevel() const; void SetBoundLevel(Level* level); };