Loading and unloading working
This commit is contained in:
parent
6ee3cc146f
commit
946c9e0027
@ -1,83 +0,0 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
/*
|
||||
class DataSource {
|
||||
public:
|
||||
using DataImporter = [ClassOfTheDataImporter]
|
||||
};
|
||||
*/
|
||||
using StorageMetadata = std::unordered_map<std::string, std::string>;
|
||||
template <typename T>
|
||||
concept HasMetadata = requires(const std::string& location) {
|
||||
{ T::loadMetadata(location) } -> std::same_as<StorageMetadata>;
|
||||
{ T::saveMetadata(StorageMetadata{}, location) };
|
||||
};
|
||||
|
||||
class StorageData {
|
||||
public:
|
||||
StorageData() = default;
|
||||
StorageData(uint32_t dataSize) : size(dataSize), data(MakeScope<uint8_t[]>(dataSize)) {}
|
||||
|
||||
inline uint8_t* getData() { return data.get(); }
|
||||
inline const uint8_t* getData() const { return data.get(); }
|
||||
inline uint32_t getSize() const { return size; }
|
||||
inline StorageMetadata& getMetadata() { return metadata; }
|
||||
|
||||
template <typename DataImporter, typename T>
|
||||
Scope<T> deserialize();
|
||||
|
||||
template <typename DataImporter, typename T>
|
||||
static StorageData serialize(const T&);
|
||||
|
||||
inline explicit operator bool() const { return size != 0; }
|
||||
|
||||
private:
|
||||
StorageMetadata metadata;
|
||||
Scope<uint8_t[]> data = nullptr;
|
||||
uint32_t size = 0;
|
||||
};
|
||||
|
||||
template <typename DataSource>
|
||||
class StorageBackend {
|
||||
public:
|
||||
static StorageData loadData(const std::string& location);
|
||||
static void saveData(const std::string& location, const StorageData& data);
|
||||
|
||||
static StorageMetadata loadMetadata(const std::string& location);
|
||||
static void saveMetadata(const StorageMetadata& metadata, const std::string& location);
|
||||
|
||||
static std::vector<std::string> indexResources(const std::string& location);
|
||||
};
|
||||
|
||||
template <typename DataSource>
|
||||
class DataManager {
|
||||
public:
|
||||
template <typename T>
|
||||
static Scope<T> load(const std::string& dataId) {
|
||||
StorageData data = StorageBackend<DataSource>::loadData(dataId);
|
||||
|
||||
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||
data.getMetadata() = StorageBackend<DataSource>::loadMetadata(dataId);
|
||||
data.getMetadata()["dataId"] = dataId;
|
||||
}
|
||||
|
||||
return data.deserialize<typename DataSource::DataImporter, T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void store(const std::string& dataId, T& value) {
|
||||
StorageData data = StorageData::serialize<typename DataSource::DataImporter, T>(value);
|
||||
StorageBackend<DataSource>::saveData(dataId, data);
|
||||
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||
StorageBackend<DataSource>::saveMetadata(data.getMetadata(), dataId);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
#define DEER_RESOURCE_PATH "Assets"
|
||||
|
||||
#define DEER_VOXEL_PATH "Voxels"
|
||||
#define DEER_VOXEL_DATA_PATH "Voxels/Data"
|
||||
#define DEER_VOXEL_ASPECT_PATH "Voxels/Visuals"
|
||||
#define DEER_VOXEL_TEXTURE_PATH "Voxels/Textures"
|
||||
#define DEER_VOXEL_SHADER_PATH "Voxels/Shaders"
|
||||
|
||||
#define DEER_EDITOR_PATH "Editor"
|
||||
#define DEER_EDITOR_PANEL_PATH "Editor/Panels"
|
||||
#define DEER_EDITOR_SERVICE_PATH "Editor/Services"
|
||||
|
||||
#define DEER_MESH_EXTENSION ".dmesh"
|
||||
#define DEER_SHADER_EXTENSION ".glsl"
|
||||
#define DEER_SCRIPT_EXTENSION ".as"
|
||||
|
||||
#define DEER_BIN_PATH "bin"
|
||||
#define DEER_TEMP_PATH "tmp"
|
||||
#define DEER_NULL_PATH "null"
|
||||
|
||||
namespace Deer {
|
||||
|
||||
struct DirectoryData {
|
||||
std::vector<Path> dirs;
|
||||
std::vector<Path> elements;
|
||||
};
|
||||
|
||||
// Namespace to manage memory interactions
|
||||
namespace DataStore {
|
||||
// Clears the cache of dir data
|
||||
void clearCache();
|
||||
|
||||
// Rerturns a directory data with the elements relative to the id
|
||||
const DirectoryData& getDirData(const Path& id, const Path& dir, const char* extension);
|
||||
|
||||
// TODO: Add safety
|
||||
// Returns the data of the specified file path
|
||||
bool loadFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size);
|
||||
// Returns the data of the specified file path avoiding extension
|
||||
bool loadGlobalFileData(const Path& id, const Path& name, uint8_t** data, uint32_t* size);
|
||||
void freeFileData(uint8_t*);
|
||||
|
||||
void createFolder(const Path& path);
|
||||
|
||||
void saveFile(const Path&, uint8_t* data, uint32_t size);
|
||||
uint8_t* readFile(const Path&, uint32_t* size);
|
||||
void deleteFile(const Path&);
|
||||
|
||||
// Refactor----
|
||||
void compressFiles(std::vector<Path> files, const Path& path);
|
||||
std::vector<Path> getFiles(const Path& path,
|
||||
const std::string& extension);
|
||||
// Refactor----
|
||||
} // namespace DataStore
|
||||
} // namespace Deer
|
||||
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Components.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Resource.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
#pragma once
|
||||
#include "DeerCore/DataManagment.h"
|
||||
#include "DeerCore/Log.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
template <typename T>
|
||||
class ResourceManager;
|
||||
|
||||
template <typename T>
|
||||
class Resource {
|
||||
public:
|
||||
int32_t getResourceId() const { return resourceId; }
|
||||
|
||||
bool isValid() const { return ResourceManager<T>::isValid(*this); }
|
||||
T& getData() { return ResourceManager<T>::getResourceData(*this); }
|
||||
|
||||
const std::string& getStorageId() const { return ResourceManager<T>::getStorageId(*this); }
|
||||
|
||||
inline explicit operator bool() const { return resourceId >= 0; }
|
||||
|
||||
static Resource<T> unsafeFromId(int32_t id) {
|
||||
Resource<T> res;
|
||||
res.resourceId = id;
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
// -1 = no resource loaded
|
||||
int32_t resourceId = -1;
|
||||
friend ResourceManager<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ResourceBuilder {
|
||||
public:
|
||||
using BaseDataType = char;
|
||||
static Scope<T> buildResource(const BaseDataType& baseData) {
|
||||
static_assert(sizeof(T) == 0, "ResourceBuilder must be specialized for this type T");
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ResourceManager {
|
||||
private:
|
||||
struct ResourceData {
|
||||
public:
|
||||
ResourceData(const std::string& _resourceId, Scope<T>&& _data)
|
||||
: storageId(_resourceId), data(std::move(_data)) {}
|
||||
|
||||
Scope<T> data;
|
||||
const std::string storageId;
|
||||
};
|
||||
|
||||
static std::vector<ResourceData> resources;
|
||||
static std::unordered_map<std::string, Resource<T>> resourceCache;
|
||||
|
||||
public:
|
||||
template <typename DataSource>
|
||||
static Resource<T> loadResource(const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
using ResourceBuilderBaseDataType = typename ResourceBuilder<T>::BaseDataType;
|
||||
Scope<T> data;
|
||||
|
||||
if constexpr (!std::is_void_v<ResourceBuilderBaseDataType>) {
|
||||
Scope<ResourceBuilderBaseDataType> baseData = DataManager<DataSource>::template load<ResourceBuilderBaseDataType>(storageId);
|
||||
if (!baseData) {
|
||||
const char* baseDataType = abi::__cxa_demangle(typeid(ResourceBuilderBaseDataType).name(), 0, 0, nullptr);
|
||||
const char* dataType = abi::__cxa_demangle(typeid(T).name(), 0, 0, nullptr);
|
||||
DEER_CORE_ERROR("Error loading base resource {} for resource {} with id {}", baseDataType, dataType, storageId.c_str());
|
||||
return Resource<T>();
|
||||
}
|
||||
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
||||
} else {
|
||||
data = ResourceBuilder<T>::buildResource(); // No base data
|
||||
}
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({storageId, std::move(data)});
|
||||
resourceCache[storageId] = resource;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static Resource<T> getResource(const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
return Resource<T>();
|
||||
}
|
||||
|
||||
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({storageId, std::move(data)});
|
||||
resourceCache[storageId] = resource;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static void unloadResources() {
|
||||
resourceCache.clear();
|
||||
resources.clear();
|
||||
}
|
||||
|
||||
static inline bool isValid(Resource<T> res) {
|
||||
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
||||
}
|
||||
|
||||
static inline const std::string& getStorageId(Resource<T> res) {
|
||||
const static std::string invalid("NULL");
|
||||
if (!isValid(res))
|
||||
return invalid;
|
||||
|
||||
return resources[res.resourceId].storageId;
|
||||
}
|
||||
|
||||
static T& getResourceData(Resource<T> res) {
|
||||
return *resources[res.resourceId].data;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
||||
template <typename T>
|
||||
std::unordered_map<std::string, Resource<T>> ResourceManager<T>::resourceCache;
|
||||
} // namespace Deer
|
||||
@ -35,7 +35,7 @@ namespace Deer {
|
||||
std::string baseTypeName;
|
||||
std::string moduleName;
|
||||
std::vector<SystemEvent> events;
|
||||
SystemDescription(const std::string& _baseTypeName, const std::string& _moduleName, const std::vector<SystemEvent>& _events = {}) : baseTypeName(_baseTypeName), moduleName(_moduleName), events(_events) {}
|
||||
SystemDescription(const std::string& _baseTypeName = "", const std::string& _moduleName = "", const std::vector<SystemEvent>& _events = {}) : baseTypeName(_baseTypeName), moduleName(_moduleName), events(_events) {}
|
||||
};
|
||||
|
||||
// Functions called by Engine
|
||||
|
||||
31
Deer/Include/DeerCore/Serialization/WorldSettings.h
Normal file
31
Deer/Include/DeerCore/Serialization/WorldSettings.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/Mesh.h"
|
||||
#include "DeerRender/Shader.h"
|
||||
|
||||
#include "DeerRender/Tools/Memory.h"
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
namespace Deer {
|
||||
struct WorldSerializationSettings {
|
||||
#ifdef DEER_RENDER
|
||||
bool includeServer = false;
|
||||
bool includeClient = true;
|
||||
|
||||
std::function<Scope<MeshData>(const Path&)> meshLoadingFunction = nullptr;
|
||||
std::function<Scope<ShaderData>(const Path&)> shaderLoadingFunction = nullptr;
|
||||
#else
|
||||
bool includeServer = true;
|
||||
bool includeClient = false;
|
||||
#endif
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& archive) {
|
||||
archive(CEREAL_NVP(includeServer));
|
||||
archive(CEREAL_NVP(includeClient));
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Serialization/WorldSettings.h"
|
||||
#include "DeerCore/Tools/Path.h"
|
||||
|
||||
namespace Deer {
|
||||
@ -7,8 +8,9 @@ namespace Deer {
|
||||
|
||||
namespace Universe {
|
||||
World* createWorld(const WorldSettings&);
|
||||
World* loadWorldFromJson(const WorldSettings&, WorldSerializationSettings&, const Path&);
|
||||
|
||||
void saveWorldInJson(World*, const Path& path);
|
||||
void saveWorldInJson(World*, WorldSerializationSettings& serializationSettings, const Path& path);
|
||||
|
||||
void destroyAllWorlds();
|
||||
void flushDestroyedWorlds();
|
||||
|
||||
@ -1,2 +1,78 @@
|
||||
#pragma once
|
||||
#include "DeerCore/DataManagment.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Tools/TypeDefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
|
||||
using StorageMetadata = std::unordered_map<std::string, std::string>;
|
||||
template <typename T>
|
||||
concept HasMetadata = requires(const std::string& location) {
|
||||
{ T::loadMetadata(location) } -> std::same_as<StorageMetadata>;
|
||||
{ T::saveMetadata(StorageMetadata{}, location) };
|
||||
};
|
||||
|
||||
class StorageData {
|
||||
public:
|
||||
StorageData() = default;
|
||||
StorageData(uint32_t dataSize) : size(dataSize), data(MakeScope<uint8_t[]>(dataSize)) {}
|
||||
|
||||
inline uint8_t* getData() { return data.get(); }
|
||||
inline const uint8_t* getData() const { return data.get(); }
|
||||
inline uint32_t getSize() const { return size; }
|
||||
inline StorageMetadata& getMetadata() { return metadata; }
|
||||
|
||||
template <typename DataImporter, typename T>
|
||||
Scope<T> deserialize();
|
||||
|
||||
template <typename DataImporter, typename T>
|
||||
static StorageData serialize(const T&);
|
||||
|
||||
inline explicit operator bool() const { return size != 0; }
|
||||
|
||||
private:
|
||||
StorageMetadata metadata;
|
||||
Scope<uint8_t[]> data = nullptr;
|
||||
uint32_t size = 0;
|
||||
};
|
||||
|
||||
template <typename DataSource>
|
||||
class StorageBackend {
|
||||
public:
|
||||
static StorageData loadData(const std::string& location);
|
||||
static void saveData(const std::string& location, const StorageData& data);
|
||||
|
||||
static StorageMetadata loadMetadata(const std::string& location);
|
||||
static void saveMetadata(const StorageMetadata& metadata, const std::string& location);
|
||||
|
||||
static std::vector<std::string> indexResources(const std::string& location);
|
||||
};
|
||||
|
||||
template <typename DataSource>
|
||||
class DataManager {
|
||||
public:
|
||||
template <typename T>
|
||||
static Scope<T> load(const std::string& dataId) {
|
||||
StorageData data = StorageBackend<DataSource>::loadData(dataId);
|
||||
|
||||
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||
data.getMetadata() = StorageBackend<DataSource>::loadMetadata(dataId);
|
||||
data.getMetadata()["dataId"] = dataId;
|
||||
}
|
||||
|
||||
return data.deserialize<typename DataSource::DataImporter, T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void store(const std::string& dataId, T& value) {
|
||||
StorageData data = StorageData::serialize<typename DataSource::DataImporter, T>(value);
|
||||
StorageBackend<DataSource>::saveData(dataId, data);
|
||||
if constexpr (HasMetadata<StorageBackend<DataSource>>) {
|
||||
StorageBackend<DataSource>::saveMetadata(data.getMetadata(), dataId);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,2 +1,140 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Resource.h"
|
||||
#include "DeerRender/DataManagment.h"
|
||||
#include "DeerRender/Log.h"
|
||||
#include "DeerRender/Tools/Memory.h"
|
||||
#include "DeerRender/Tools/Path.h"
|
||||
#include "DeerRender/Tools/TypeDefs.h"
|
||||
|
||||
#include <cxxabi.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Deer {
|
||||
template <typename T>
|
||||
class ResourceManager;
|
||||
|
||||
template <typename T>
|
||||
class Resource {
|
||||
public:
|
||||
int32_t getResourceId() const { return resourceId; }
|
||||
|
||||
bool isValid() const { return ResourceManager<T>::isValid(*this); }
|
||||
T& getData() { return ResourceManager<T>::getResourceData(*this); }
|
||||
|
||||
const std::string& getStorageId() const { return ResourceManager<T>::getStorageId(*this); }
|
||||
|
||||
inline explicit operator bool() const { return resourceId >= 0; }
|
||||
|
||||
static Resource<T> unsafeFromId(int32_t id) {
|
||||
Resource<T> res;
|
||||
res.resourceId = id;
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
// -1 = no resource loaded
|
||||
int32_t resourceId = -1;
|
||||
friend ResourceManager<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ResourceBuilder {
|
||||
public:
|
||||
using BaseDataType = char;
|
||||
static Scope<T> buildResource(const BaseDataType& baseData) {
|
||||
static_assert(sizeof(T) == 0, "ResourceBuilder must be specialized for this type T");
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ResourceManager {
|
||||
private:
|
||||
struct ResourceData {
|
||||
public:
|
||||
ResourceData(const std::string& _resourceId, Scope<T>&& _data)
|
||||
: storageId(_resourceId), data(std::move(_data)) {}
|
||||
|
||||
Scope<T> data;
|
||||
const std::string storageId;
|
||||
};
|
||||
|
||||
static std::vector<ResourceData> resources;
|
||||
static std::unordered_map<std::string, Resource<T>> resourceCache;
|
||||
|
||||
public:
|
||||
template <typename DataSource>
|
||||
static Resource<T> loadResource(const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
using ResourceBuilderBaseDataType = typename ResourceBuilder<T>::BaseDataType;
|
||||
Scope<T> data;
|
||||
|
||||
if constexpr (!std::is_void_v<ResourceBuilderBaseDataType>) {
|
||||
Scope<ResourceBuilderBaseDataType> baseData = DataManager<DataSource>::template load<ResourceBuilderBaseDataType>(storageId);
|
||||
if (!baseData) {
|
||||
const char* baseDataType = abi::__cxa_demangle(typeid(ResourceBuilderBaseDataType).name(), 0, 0, nullptr);
|
||||
const char* dataType = abi::__cxa_demangle(typeid(T).name(), 0, 0, nullptr);
|
||||
DEER_CORE_ERROR("Error loading base resource {} for resource {} with id {}", baseDataType, dataType, storageId.c_str());
|
||||
return Resource<T>();
|
||||
}
|
||||
data = ResourceBuilder<T>::buildResource(*baseData.get());
|
||||
} else {
|
||||
data = ResourceBuilder<T>::buildResource(); // No base data
|
||||
}
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({storageId, std::move(data)});
|
||||
resourceCache[storageId] = resource;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static Resource<T> getResource(const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
return Resource<T>();
|
||||
}
|
||||
|
||||
static Resource<T> loadResourceFromData(const typename ResourceBuilder<T>::BaseDataType& resourceData, const std::string& storageId) {
|
||||
if (resourceCache.contains(storageId))
|
||||
return resourceCache[storageId];
|
||||
|
||||
Scope<T> data = ResourceBuilder<T>::buildResource(resourceData);
|
||||
|
||||
Resource<T> resource = Resource<T>::unsafeFromId(resources.size());
|
||||
resources.push_back({storageId, std::move(data)});
|
||||
resourceCache[storageId] = resource;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
static void unloadResources() {
|
||||
resourceCache.clear();
|
||||
resources.clear();
|
||||
}
|
||||
|
||||
static inline bool isValid(Resource<T> res) {
|
||||
return res.resourceId >= 0 && res.resourceId < static_cast<int32_t>(resources.size());
|
||||
}
|
||||
|
||||
static inline const std::string& getStorageId(Resource<T> res) {
|
||||
const static std::string invalid("NULL");
|
||||
if (!isValid(res))
|
||||
return invalid;
|
||||
|
||||
return resources[res.resourceId].storageId;
|
||||
}
|
||||
|
||||
static T& getResourceData(Resource<T> res) {
|
||||
return *resources[res.resourceId].data;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::vector<typename ResourceManager<T>::ResourceData> ResourceManager<T>::resources;
|
||||
template <typename T>
|
||||
std::unordered_map<std::string, Resource<T>> ResourceManager<T>::resourceCache;
|
||||
} // namespace Deer
|
||||
|
||||
@ -6,6 +6,11 @@
|
||||
|
||||
#include "DeerCore/Serialization/Components/TransformComponent.h"
|
||||
|
||||
#ifdef DEER_RENDER
|
||||
#include "DeerRender/Serialization/Components/MeshComponentSerialization.h"
|
||||
#include "DeerRender/Serialization/Components/ShaderComponentSerialization.h"
|
||||
#endif
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <string>
|
||||
|
||||
@ -16,18 +21,34 @@ namespace Deer {
|
||||
uint32_t entityId;
|
||||
|
||||
template <class Archive, class T, class S>
|
||||
void saveComponent(Archive& archive, Entity& entity) {
|
||||
void saveComponent(Archive& archive, Entity& entity, const char* name) const {
|
||||
std::string containsComponentString = "Contains_";
|
||||
containsComponentString += typeid(T).name();
|
||||
containsComponentString += name;
|
||||
|
||||
bool hasComponent = entity.hasComponent<T>();
|
||||
archive(cereal::make_nvp(containsComponentString.c_str(), hasComponent));
|
||||
if (hasComponent) {
|
||||
S serialization;
|
||||
serialization.component = entity.getComponent<T>();
|
||||
serialization.settings = settings;
|
||||
S serialization{
|
||||
.component = entity.getComponent<T>(),
|
||||
.settings = settings};
|
||||
|
||||
archive(cereal::make_nvp(typeid(T).name(), serialization));
|
||||
archive(cereal::make_nvp(name, serialization));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive, class T, class S>
|
||||
void loadComponent(Archive& archive, Entity& entity, const char* name) {
|
||||
std::string containsComponentString = "Contains_";
|
||||
containsComponentString += name;
|
||||
|
||||
bool hasComponent;
|
||||
archive(cereal::make_nvp(containsComponentString.c_str(), hasComponent));
|
||||
if (hasComponent) {
|
||||
S serialization{
|
||||
.component = entity.addComponent<T>(),
|
||||
.settings = settings};
|
||||
|
||||
archive(cereal::make_nvp(name, serialization));
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,14 +64,46 @@ namespace Deer {
|
||||
archive(cereal::make_nvp("NetworkBehaviour", tag.networkBehaviour));
|
||||
archive(cereal::make_nvp("Parent", relation.parent_id));
|
||||
|
||||
TransformComponentSerialization serialization;
|
||||
serialization.settings = settings;
|
||||
serialization.component = entity.getComponent<T>();
|
||||
archive(cereal::make_nvp(typeid(TransformComponent).name(), serialization));
|
||||
TransformComponentSerialization transformSerialization{
|
||||
.settings = settings,
|
||||
.component = entity.getComponent<TransformComponent>()};
|
||||
archive(cereal::make_nvp("TransformComponent", transformSerialization));
|
||||
|
||||
if (settings.includeClient) {
|
||||
#ifdef DEER_RENDER
|
||||
saveComponent<Archive, MeshComponent, MeshComponentSerialization>(archive, entity, "MeshComponent");
|
||||
saveComponent<Archive, ShaderComponent, ShaderComponentSerialization>(archive, entity, "ShaderComponent");
|
||||
#else
|
||||
DEER_CORE_ERROR("Can not include client on Deer Core Headless Compile");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load(Archive& archive) {
|
||||
archive(cereal::make_nvp("Id", entityId));
|
||||
Entity& entity = entityEnvironment->createEntityWithId(entityId);
|
||||
|
||||
TagComponent& tag = entity.getComponent<TagComponent>();
|
||||
RelationshipComponent& relation = entity.getComponent<RelationshipComponent>();
|
||||
|
||||
archive(cereal::make_nvp("Tag", tag.tag));
|
||||
archive(cereal::make_nvp("NetworkBehaviour", tag.networkBehaviour));
|
||||
archive(cereal::make_nvp("Parent", tag.networkBehaviour));
|
||||
|
||||
TransformComponentSerialization transformSerialization{
|
||||
.settings = settings,
|
||||
.component = entity.getComponent<TransformComponent>()};
|
||||
archive(cereal::make_nvp("TransformComponent", transformSerialization));
|
||||
|
||||
if (settings.includeClient) {
|
||||
#ifdef DEER_RENDER
|
||||
loadComponent<Archive, MeshComponent, MeshComponentSerialization>(archive, entity, "MeshComponent");
|
||||
loadComponent<Archive, ShaderComponent, ShaderComponentSerialization>(archive, entity, "ShaderComponent");
|
||||
#else
|
||||
DEER_CORE_ERROR("Can not include client on Deer Core Headless Compile");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -18,7 +18,7 @@ namespace Deer {
|
||||
void save(Archive& archive) const {
|
||||
std::vector<EntitySerialization> entities;
|
||||
|
||||
size_t entityIndex = 0;
|
||||
uint32_t entityIndex = 0;
|
||||
size_t remainingEntities = entityEnvironment->getEntityCount();
|
||||
while (remainingEntities > 0) {
|
||||
if (!entityEnvironment->entityExists(entityIndex)) {
|
||||
@ -43,13 +43,12 @@ namespace Deer {
|
||||
entityIndex++;
|
||||
}
|
||||
|
||||
entities.push_back({});
|
||||
EntitySerialization entityS{
|
||||
.settings = settings,
|
||||
.entityEnvironment = entityEnvironment,
|
||||
.entityId = entityIndex};
|
||||
|
||||
EntitySerialization& entityS = entities.push_back();
|
||||
|
||||
entityS.settings = settings;
|
||||
entityS.entityId = entityEnvironment;
|
||||
entityS.entityId = entityIndex;
|
||||
entities.push_back(entityS);
|
||||
|
||||
remainingEntities--;
|
||||
entityIndex++;
|
||||
@ -63,14 +62,20 @@ namespace Deer {
|
||||
template <class Archive>
|
||||
void load(Archive& archive) {
|
||||
size_t entitySize;
|
||||
archive(cereal::make_nvp("Entities", entitySize));
|
||||
archive(cereal::make_size_tag(entitySize));
|
||||
|
||||
std::vector<uint32_t> entities;
|
||||
for (size_t i = 0; i < entitySize; i++) {
|
||||
EntitySerialization entityS;
|
||||
entityS.entityEnvironment = entityEnvironment;
|
||||
entityS.settings = settings;
|
||||
|
||||
EntitySerialization entityS{.settings = settings, .entityEnvironment = entityEnvironment};
|
||||
archive(entityS);
|
||||
|
||||
entities.push_back(entityS.entityId);
|
||||
}
|
||||
|
||||
for (uint32_t entity_id : entities) {
|
||||
Entity& entity = entityEnvironment->getEntity(entity_id);
|
||||
RelationshipComponent& tag = entity.getComponent<RelationshipComponent>();
|
||||
entity.setParent(entityEnvironment->getEntity(tag.parent_id));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -8,18 +8,15 @@ namespace Deer {
|
||||
class World;
|
||||
|
||||
struct WorldSerialization {
|
||||
WorldSerializationSettings settings;
|
||||
EntityEnvironment* entityEnv;
|
||||
uint32_t entityId;
|
||||
WorldSerializationSettings& settings;
|
||||
World* world;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& archive) {
|
||||
EntityEnvironmentSerialization entityEnvironment;
|
||||
entityEnvironment.settings = settings;
|
||||
entityEnvironment.entityEnvironment = world->entityEnvironment.get();
|
||||
EntityEnvironmentSerialization entityEnvironment{
|
||||
.settings = settings,
|
||||
.entityEnvironment = world->entityEnvironment.get()};
|
||||
|
||||
archive(cereal::make_nvp("SerializationSettings", settings));
|
||||
archive(cereal::make_nvp("EntityEnvironment", entityEnvironment));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace Deer {
|
||||
struct WorldSerializationSettings {
|
||||
bool includeServer;
|
||||
bool includeClient;
|
||||
|
||||
WorldSerializationSettings() {
|
||||
#ifdef DEER_RENDER
|
||||
includeServer = false;
|
||||
includeClient = true;
|
||||
#else
|
||||
includeServer = true;
|
||||
includeClient = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& archive) {
|
||||
archive(CEREAL_NVP(includeServer));
|
||||
archive(CEREAL_NVP(includeClient));
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,6 +1,35 @@
|
||||
#include "DeerCore/Universe.h"
|
||||
|
||||
#include "DeerCore/Serialization/World.h"
|
||||
#include "cereal/archives/json.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace Deer {
|
||||
void Universe::saveWorldInJson(World* world, const Path& path) {
|
||||
void Universe::saveWorldInJson(World* world, WorldSerializationSettings& serializationSettings, const Path& path) {
|
||||
std::ofstream file(path);
|
||||
cereal::JSONOutputArchive archive(file);
|
||||
|
||||
WorldSerialization worldSerialization{
|
||||
.settings = serializationSettings,
|
||||
.world = world};
|
||||
|
||||
archive(cereal::make_nvp("SerializationSettings", serializationSettings));
|
||||
archive(cereal::make_nvp("World", worldSerialization));
|
||||
}
|
||||
|
||||
World* Universe::loadWorldFromJson(const WorldSettings& worldSettings, WorldSerializationSettings& serializationSettings, const Path& path) {
|
||||
std::ifstream file(path);
|
||||
cereal::JSONInputArchive archive(file);
|
||||
|
||||
World* world = Universe::createWorld(worldSettings);
|
||||
WorldSerialization worldSerialization{
|
||||
.settings = serializationSettings,
|
||||
.world = world};
|
||||
|
||||
archive(cereal::make_nvp("SerializationSettings", serializationSettings));
|
||||
archive(cereal::make_nvp("World", worldSerialization));
|
||||
|
||||
return world;
|
||||
}
|
||||
} // namespace Deer
|
||||
@ -20,7 +20,7 @@ namespace Deer {
|
||||
}
|
||||
|
||||
World::~World() {
|
||||
DEER_CORE_ASSERT(executingState == WorldState::Stopped, "Invalid executing state while destroying world");
|
||||
DEER_CORE_ASSERT(executingState == WorldState::ReadyToDestroy, "Invalid executing state while destroying world");
|
||||
}
|
||||
|
||||
void World::stopExecution() {
|
||||
|
||||
@ -65,6 +65,10 @@ namespace Deer {
|
||||
RenderCommand::init();
|
||||
RenderUtils::initializeRenderUtils();
|
||||
|
||||
Builtin::cube();
|
||||
Builtin::simpleShader();
|
||||
Builtin::sphere();
|
||||
|
||||
ImGuiLayer::init(*window);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Serialization/WorldSettings.h"
|
||||
|
||||
#include "DeerRender/Components.h"
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace Deer {
|
||||
struct MeshComponentSerialization {
|
||||
WorldSerializationSettings& settings;
|
||||
MeshComponent& component;
|
||||
|
||||
template <class Archive>
|
||||
void save(Archive& archive) const {
|
||||
archive(cereal::make_nvp("IsActive", component.active));
|
||||
archive(cereal::make_nvp("Mesh", component.mesh.getStorageId()));
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load(Archive& archive) {
|
||||
std::string storageId;
|
||||
|
||||
archive(cereal::make_nvp("IsActive", component.active));
|
||||
archive(cereal::make_nvp("Mesh", storageId));
|
||||
|
||||
Scope<MeshData> meshData = settings.meshLoadingFunction(storageId);
|
||||
|
||||
Resource<GPUMesh> mesh = ResourceManager<GPUMesh>::loadResourceFromData(*meshData.get(), storageId);
|
||||
component.mesh = mesh;
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Serialization/WorldSettings.h"
|
||||
|
||||
#include "DeerRender/Components.h"
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace Deer {
|
||||
struct ShaderComponentSerialization {
|
||||
WorldSerializationSettings& settings;
|
||||
ShaderComponent& component;
|
||||
|
||||
template <class Archive>
|
||||
void save(Archive& archive) const {
|
||||
archive(cereal::make_nvp("Shader", component.shader.getStorageId()));
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void load(Archive& archive) {
|
||||
std::string storageId;
|
||||
|
||||
archive(cereal::make_nvp("Shader", storageId));
|
||||
|
||||
Scope<ShaderData> shaderData = settings.shaderLoadingFunction(storageId);
|
||||
|
||||
Resource<Shader> shader = ResourceManager<Shader>::loadResourceFromData(*shaderData.get(), storageId);
|
||||
component.shader = shader;
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
#include "DeerCore/Serialization/WorldSettings.h"
|
||||
|
||||
#include "DeerRender/Components.h"
|
||||
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace Deer {
|
||||
struct MeshComponentSerialization {
|
||||
WorldSerializationSettings& settings;
|
||||
TransformComponent& component;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& archive) {
|
||||
archive(cereal::make_nvp("Position", component.position));
|
||||
archive(cereal::make_nvp("Scale", component.scale));
|
||||
archive(cereal::make_nvp("Rotation", component.rotation));
|
||||
}
|
||||
};
|
||||
} // namespace Deer
|
||||
@ -5,9 +5,13 @@
|
||||
int main(int, char**);
|
||||
|
||||
namespace Deer {
|
||||
class World;
|
||||
|
||||
namespace DeerStudio {
|
||||
void onRender();
|
||||
void onUpdate();
|
||||
extern World* world;
|
||||
|
||||
void worldUpdate(World&);
|
||||
void worldRender(World&);
|
||||
|
||||
void onEvent(Event& e);
|
||||
void main();
|
||||
@ -16,5 +20,6 @@ namespace Deer {
|
||||
|
||||
// Other
|
||||
void onPanelMenuBar();
|
||||
void worldManagerMenu();
|
||||
} // namespace DeerStudio
|
||||
} // namespace Deer
|
||||
|
||||
@ -24,6 +24,5 @@ namespace Deer {
|
||||
CScriptDictionary* setResourceMetadata(std::string& resource);
|
||||
|
||||
ResourceType getResourceType(std::string&);
|
||||
|
||||
} // namespace StudioAPI
|
||||
} // namespace Deer
|
||||
@ -4,7 +4,8 @@ namespace Deer {
|
||||
class World;
|
||||
|
||||
namespace StudioPanel {
|
||||
void init(World*);
|
||||
void init();
|
||||
void setWorld(World*);
|
||||
|
||||
void update();
|
||||
void render();
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Deer {
|
||||
class FrameBuffer;
|
||||
|
||||
namespace DeerStudio {
|
||||
Universe::WorldHandle mainWorld;
|
||||
World* world;
|
||||
|
||||
void onUpdate();
|
||||
void onRender();
|
||||
@ -29,6 +29,7 @@ namespace Deer {
|
||||
void main() {
|
||||
Engine::init();
|
||||
Engine::setEventCallback(DeerStudio::onEvent);
|
||||
StudioPanel::init();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20, 20));
|
||||
initializeFonts();
|
||||
@ -41,10 +42,12 @@ namespace Deer {
|
||||
.renderFrequency = 166,
|
||||
};
|
||||
|
||||
mainWorld = Universe::createWorld(worldSettings);
|
||||
StudioPanel::init(&Universe::getWorld(mainWorld));
|
||||
world = Universe::createWorld(worldSettings);
|
||||
|
||||
Universe::getWorld(mainWorld).execute();
|
||||
while (world) {
|
||||
StudioPanel::setWorld(world);
|
||||
world->execute();
|
||||
}
|
||||
|
||||
Engine::shutdown();
|
||||
} // namespace DeerStudio
|
||||
@ -80,8 +83,7 @@ namespace Deer {
|
||||
}
|
||||
|
||||
static bool p_open = true;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,
|
||||
ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::Begin("DockSpace Demo", &p_open, window_flags);
|
||||
@ -93,17 +95,17 @@ namespace Deer {
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
if (ImGui::BeginMenu("Panel")) {
|
||||
onPanelMenuBar();
|
||||
if (ImGui::BeginMenu("World")) {
|
||||
DeerStudio::worldManagerMenu();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("Reload Editor")) {
|
||||
}
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
StudioPanel::render();
|
||||
if (world.getExecutionState() == Deer::WorldState::Executing)
|
||||
StudioPanel::render();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
@ -117,7 +119,8 @@ namespace Deer {
|
||||
}
|
||||
|
||||
bool onWindowCloseEvent(WindowCloseEvent&) {
|
||||
Universe::getWorld(mainWorld).stopExecution();
|
||||
world->stopExecution();
|
||||
world = nullptr;
|
||||
return true;
|
||||
}
|
||||
} // namespace DeerStudio
|
||||
|
||||
@ -13,12 +13,15 @@ namespace Deer {
|
||||
void renderSystem(ScriptSystem* system);
|
||||
} // namespace StudioPanel
|
||||
|
||||
void StudioPanel::init(World* world) {
|
||||
void StudioPanel::init() {
|
||||
StudioScripting::registerStudioScripting();
|
||||
Scripting::registerInterface("Panel");
|
||||
Scripting::registerInterfaceFunction("Panel", "onImGui", Scripting::EventType::void_event);
|
||||
|
||||
Scripting::compileFiles("Editor/Scripts", "Editor");
|
||||
}
|
||||
|
||||
void StudioPanel::setWorld(World* world) {
|
||||
Scripting::SystemDescription systemDescription("Panel", "Editor");
|
||||
systemDescription.events.push_back(Scripting::SystemEvent("onInit", Scripting::EventType::void_event));
|
||||
systemDescription.events.push_back(Scripting::SystemEvent("onShutdown", Scripting::EventType::void_event));
|
||||
@ -67,5 +70,6 @@ namespace Deer {
|
||||
|
||||
void StudioPanel::shutdown() {
|
||||
editorInstance->executeOnGroup_voidEvent(1);
|
||||
studioPanelEnvironment.release();
|
||||
}
|
||||
} // namespace Deer
|
||||
47
DeerStudio/src/DeerStudio/WorldManager.cpp
Normal file
47
DeerStudio/src/DeerStudio/WorldManager.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "DeerCore/Serialization/WorldSettings.h"
|
||||
#include "DeerCore/Tools/Memory.h"
|
||||
#include "DeerCore/Universe.h"
|
||||
|
||||
#include "DeerStudio/EditorDataImporter.h"
|
||||
#include "DeerStudio/EditorDataSource.h"
|
||||
#include "DeerStudio/StudioPanel.h"
|
||||
|
||||
#include "DeerCore/World.h"
|
||||
#include "DeerStudio/DeerStudio.h"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace Deer {
|
||||
template <typename T>
|
||||
Scope<T> loadResourceData(const Path& storageId) {
|
||||
StorageData storageData = StorageBackend<EditorDataSource>::loadData(storageId);
|
||||
return storageData.deserialize<EditorDataImporter, T>();
|
||||
}
|
||||
|
||||
void DeerStudio::worldManagerMenu() {
|
||||
if (ImGui::MenuItem("Save world")) {
|
||||
WorldSerializationSettings serializationSettings{
|
||||
.includeServer = true,
|
||||
.includeClient = true};
|
||||
Universe::saveWorldInJson(world, serializationSettings, "Worlds/world.json");
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Load world")) {
|
||||
StudioPanel::shutdown();
|
||||
world->destroy();
|
||||
|
||||
WorldSettings worldSettings = {
|
||||
.updateCallback = worldUpdate,
|
||||
.updateFrequency = 60,
|
||||
.renderCallback = worldRender,
|
||||
.renderFrequency = 166,
|
||||
};
|
||||
|
||||
WorldSerializationSettings serializationSettings{
|
||||
.meshLoadingFunction = loadResourceData<MeshData>,
|
||||
.shaderLoadingFunction = loadResourceData<ShaderData>};
|
||||
|
||||
World* world_new = Universe::loadWorldFromJson(worldSettings, serializationSettings, "Worlds/world.json");
|
||||
world = world_new;
|
||||
}
|
||||
}
|
||||
} // namespace Deer
|
||||
135
Worlds/world.json
Normal file
135
Worlds/world.json
Normal file
@ -0,0 +1,135 @@
|
||||
{
|
||||
"SerializationSettings": {
|
||||
"includeServer": true,
|
||||
"includeClient": true
|
||||
},
|
||||
"World": {
|
||||
"EntityEnvironment": [
|
||||
{
|
||||
"Id": 0,
|
||||
"Tag": "root",
|
||||
"NetworkBehaviour": 0,
|
||||
"Parent": 0,
|
||||
"TransformComponent": {
|
||||
"Position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 1.0
|
||||
}
|
||||
},
|
||||
"Contains_MeshComponent": false,
|
||||
"Contains_ShaderComponent": false
|
||||
},
|
||||
{
|
||||
"Id": 1,
|
||||
"Tag": "node",
|
||||
"NetworkBehaviour": 0,
|
||||
"Parent": 0,
|
||||
"TransformComponent": {
|
||||
"Position": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 1.0
|
||||
}
|
||||
},
|
||||
"Contains_MeshComponent": true,
|
||||
"MeshComponent": {
|
||||
"IsActive": true,
|
||||
"Mesh": "Builtin:Cube"
|
||||
},
|
||||
"Contains_ShaderComponent": true,
|
||||
"ShaderComponent": {
|
||||
"Shader": "Builtin:SimpleShader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": 2,
|
||||
"Tag": "node",
|
||||
"NetworkBehaviour": 0,
|
||||
"Parent": 0,
|
||||
"TransformComponent": {
|
||||
"Position": {
|
||||
"x": 2.299999952316284,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 1.0
|
||||
}
|
||||
},
|
||||
"Contains_MeshComponent": true,
|
||||
"MeshComponent": {
|
||||
"IsActive": true,
|
||||
"Mesh": "Builtin:Sphere"
|
||||
},
|
||||
"Contains_ShaderComponent": true,
|
||||
"ShaderComponent": {
|
||||
"Shader": "Builtin:SimpleShader"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Id": 3,
|
||||
"Tag": "node",
|
||||
"NetworkBehaviour": 0,
|
||||
"Parent": 0,
|
||||
"TransformComponent": {
|
||||
"Position": {
|
||||
"x": -3.700000047683716,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"Scale": {
|
||||
"x": 1.0,
|
||||
"y": 1.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"Rotation": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"w": 1.0
|
||||
}
|
||||
},
|
||||
"Contains_MeshComponent": true,
|
||||
"MeshComponent": {
|
||||
"IsActive": true,
|
||||
"Mesh": "train-locomotive-a.obj"
|
||||
},
|
||||
"Contains_ShaderComponent": true,
|
||||
"ShaderComponent": {
|
||||
"Shader": "shader_darkBlue.glsl"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
16
imgui.ini
16
imgui.ini
@ -1,6 +1,6 @@
|
||||
[Window][DockSpace Demo]
|
||||
Pos=0,0
|
||||
Size=1920,1011
|
||||
Size=2560,1371
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
@ -10,30 +10,30 @@ Collapsed=0
|
||||
|
||||
[Window][ViewportPanel]
|
||||
Pos=561,26
|
||||
Size=934,493
|
||||
Size=1574,853
|
||||
Collapsed=0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][PropertiesPanel]
|
||||
Pos=1497,26
|
||||
Size=423,493
|
||||
Pos=2137,26
|
||||
Size=423,853
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][ResourceExplorer]
|
||||
Pos=0,521
|
||||
Size=1920,490
|
||||
Pos=0,881
|
||||
Size=2560,490
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Window][TreePanel]
|
||||
Pos=0,26
|
||||
Size=559,493
|
||||
Size=559,853
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=1920,985 Split=Y
|
||||
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=2560,1345 Split=Y
|
||||
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,493 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=559,985 Selected=0x16E3C1E7
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1359,985 Split=X
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user