/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2021 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #ifndef __OPENSPACE_CORE___ASSETLOADER___H__ #define __OPENSPACE_CORE___ASSETLOADER___H__ #include #include #include #include #include #include struct lua_State; namespace ghoul::filesystem { class Directory; } namespace ghoul::lua { class LuaState; } namespace openspace { namespace assetloader { int onInitialize(lua_State* state); int onDeinitialize(lua_State* state); int onInitializeDependency(lua_State* state); int onDeinitializeDependency(lua_State* state); int require(lua_State* state); int exists(lua_State* state); int localResource(lua_State* state); int syncedResource(lua_State* state); int exportAsset(lua_State* state); } // namespace assetloader class AssetListener; class ResourceSynchronization; class SynchronizationWatcher; class AssetLoader { public: AssetLoader(ghoul::lua::LuaState* luaState, SynchronizationWatcher* syncWatcher, std::string assetRootDirectory); ~AssetLoader(); /** * Add the asset as a request of the root asset */ std::shared_ptr add(const std::string& identifier); /** * Remove the asset as a request of the root asset */ void remove(const std::string& identifier); /** * Enable the asset to be reused when the same path is required/requested again */ void trackAsset(std::shared_ptr asset); /** * Disable the asset from being reused when the same path is required/requested again */ void untrackAsset(Asset* asset); /** * Return the asset identified by the identifier, * if the asset is tracked. Otherwise return nullptr. */ std::shared_ptr has(const std::string& identifier) const; /// Return the root asset const Asset& rootAsset() const; /// Return the root asset Asset& rootAsset(); /** * Return the asset root directory */ const std::string& assetRootDirectory() const; /** * Load an asset */ bool loadAsset(Asset* asset); /** * Unload an asset */ void unloadAsset(Asset* asset); /** * Call the onInitialize function specified in the asset file */ void callOnInitialize(Asset* asset); /** * Call the onDeinitialize function specified in the asset file */ void callOnDeinitialize(Asset* asset); /** * Call the dependency.onInitialize function specified in the asset file */ void callOnDependencyInitialize(Asset* asset, Asset* dependant); /** * Call the dependency.onDeinitialize function specified in the asset file */ void callOnDependencyDeinitialize(Asset* asset, Asset* dependant); /** * Generate the absolute path for an asset specified as `path` * relative to `baseDirectory` */ std::string generateAssetPath(const std::string& baseDirectory, const std::string& assetPath) const; /** * Add listener to asset state changes */ void addAssetListener(AssetListener* listener); /** * Remove listener to asset state changes */ void removeAssetListener(AssetListener* listener); /** * Notify listeners about asset state change */ void assetStateChanged(Asset* asset, Asset::State state); /** * Notify listeners about new requests */ void assetRequested(Asset* parent, std::shared_ptr child); /** * Notify listeners about removed requests */ void assetUnrequested(Asset* parent, std::shared_ptr child); private: void unrequest(const std::string& identifier); void setUpAssetLuaTable(Asset* asset); void tearDownAssetLuaTable(Asset* asset); std::shared_ptr getAsset(const std::string& name); std::filesystem::path currentDirectory() const; void setCurrentAsset(Asset* asset); void addLuaDependencyTable(Asset* dependant, Asset* dependency); // Lua functions int onInitializeLua(Asset* asset); int onDeinitializeLua(Asset* asset); int onInitializeDependencyLua(Asset* dependant, Asset* dependency); int onDeinitializeDependencyLua(Asset* dependant, Asset* dependency); int requireLua(Asset* dependant); int requestLua(Asset* parent); int existsLua(Asset* asset); int localResourceLua(Asset* asset); int syncedResourceLua(Asset* asset); int exportAssetLua(Asset* asset); // Friend C closures (callable from Lua, and maps to Lua functions above) friend int assetloader::onInitialize(lua_State* state); friend int assetloader::onDeinitialize(lua_State* state); friend int assetloader::onInitializeDependency(lua_State* state); friend int assetloader::onDeinitializeDependency(lua_State* state); friend int assetloader::require(lua_State* state); friend int assetloader::exists(lua_State* state); friend int assetloader::localResource(lua_State* state); friend int assetloader::syncedResource(lua_State* state); friend int assetloader::exportAsset(lua_State* state); // Member variables std::shared_ptr _rootAsset; Asset* _currentAsset = nullptr; std::unordered_map> _trackedAssets; SynchronizationWatcher* _synchronizationWatcher; std::string _assetRootDirectory; ghoul::lua::LuaState* _luaState; // State change listeners std::vector _assetListeners; // References to Lua values std::unordered_map> _onInitializationFunctionRefs; std::unordered_map> _onDeinitializationFunctionRefs; std::unordered_map>> _onDependencyInitializationFunctionRefs; std::unordered_map>> _onDependencyDeinitializationFunctionRefs; int _assetsTableRef = 0; }; } // namespace openspace #endif // __OPENSPACE_CORE___ASSETLOADER___H__