Remodelating system

This commit is contained in:
Chewico 2026-01-06 14:20:38 +01:00
parent ba42be46ba
commit 47871fa1dc
21 changed files with 240 additions and 71 deletions

View File

@ -6,9 +6,9 @@ namespace Deer {
std::shared_ptr<spdlog::logger> Log::scriptLogger;
std::shared_ptr<spdlog::logger> Log::EditorEngineLogger;
void Log::init()
{
spdlog::set_pattern("%^[%T] %n: %v%$");
void Log::init() {
// spdlog::set_pattern("%^[%T] %n: %v%$");
spdlog::set_pattern("%n: %v%$");
coreLogger = spdlog::stdout_color_mt("Core");
clientLogger = spdlog::stdout_color_mt("Client");
@ -30,8 +30,7 @@ namespace Deer {
spdlog::drop_all();
}
void Log::coreTrace(const char* msg)
{
void Log::coreTrace(const char* msg) {
// coreLogger->trace(msg);
}
}
} // namespace Deer

View File

@ -61,9 +61,6 @@ namespace Deer {
voxelData.name.c_str());
continue;
}
// DEER_CORE_TRACE(" {0} - {1}",
// voxel.filename().generic_string().c_str(),
// voxelData.name);
uint32_t id = voxelsInfo.size();

View File

@ -56,10 +56,6 @@ namespace Deer {
continue;
}
// DEER_CORE_TRACE(" {0} - {1}",
// voxelAspectPath.filename().generic_string().c_str(),
// aspectDefinition.voxelName.c_str());
voxelsAspect[voxelID].definition = aspectDefinition;
}
@ -92,9 +88,6 @@ namespace Deer {
texturesIDs[faceTextureString] = textureID;
voxelAspect.textureFacesIDs[i] = textureID;
// DEER_CORE_TRACE(" texture {0} - id: {1}",
// faceTextureString.c_str(), textureID);
}
}
}

View File

@ -209,8 +209,6 @@ namespace Deer {
// Either of them. Don't leak shaders.
glDeleteShader(vertexShader);
DEER_CORE_TRACE(source);
// Use the infoLog as you see fit.
DEER_CORE_ERROR("Error compiling fragment shader. \n{0}", infoLog);
delete[] infoLog;

View File

@ -1,6 +1,8 @@
#pragma once
#include <vector>
#include "DeerRender/Tools/Path.h"
#include <string>
#include <unordered_map>
#include <vector>
class asIScriptEngine;
class asIScriptModule;
@ -24,6 +26,7 @@ namespace Deer {
~Service();
Service(Service&) = delete;
Service& operator=(Service&) = delete;
Service(Service&&) = default;
Service& operator=(Service&&) = default;
@ -55,12 +58,33 @@ namespace Deer {
asIScriptFunction* menuBarFunction;
};
struct ModuleDescription {
public:
int patchVersion = -1;
std::string moduleName;
std::string modulePath;
std::vector<std::string> module_requires;
};
enum class ModuleState {
NotBuilt = 0,
Building = 1,
Built = 2,
DependencyFailed = 3,
CompilationFailed = 5,
ExecutionError = 6
};
struct Module {
public:
Module(asIScriptModule*);
ModuleDescription moduleInfo;
ModuleState state = ModuleState::NotBuilt;
Module(const ModuleDescription&);
~Module();
Module(const Module&) = delete;
Module& operator=(Module&) = delete;
Module(Module&&) = default;
Module& operator=(Module&&) = default;
@ -69,19 +93,22 @@ namespace Deer {
void render();
void shutdown();
inline void invalidate() { invalidated = true; }
void extractTypes();
inline void invalidate() { state = ModuleState::ExecutionError; }
private:
asIScriptModule* angelscriptModule;
std::vector<Panel> panels;
std::vector<Service> services;
asIScriptModule* angelscriptModule;
bool invalidated = false;
};
extern asIScriptEngine* scriptEngine;
extern asIScriptContext* scriptContext;
extern CScriptBuilder scriptBuilder;
extern std::vector<Module> modules;
extern std::unordered_map<std::string, int> module_id;
extern asITypeInfo* panelBaseType;
extern asITypeInfo* serviceBaseType;

View File

@ -21,6 +21,7 @@ namespace Deer {
CScriptBuilder scriptBuilder;
std::vector<Module> modules;
std::unordered_map<std::string, int> module_id;
Module* executingModule;
asITypeInfo* panelBaseType;
@ -82,6 +83,7 @@ namespace Deer {
}
modules.clear();
module_id.clear();
if (scriptContext)
scriptContext->Release();

View File

@ -1,12 +1,17 @@
#include "DeerStudio/AngelScriptEngine.h"
#include "angelscript.h"
#include "DeerRender/Log.h"
#include "DeerStudio/AngelScriptEngine.h"
#include "DeerStudio/AngelScriptEngine/ErrorHandle.h"
#include "angelscript.h"
namespace Deer {
namespace AngelScriptEngine {
Module::Module(asIScriptModule* _angelscriptModule) {
angelscriptModule = _angelscriptModule;
Module::Module(const ModuleDescription& _mi) : moduleInfo(_mi) {}
void Module::extractTypes() {
if (state != ModuleState::Built)
return;
angelscriptModule = AngelScriptEngine::scriptEngine->GetModule(moduleInfo.moduleName.c_str());
uint32_t typeCount = angelscriptModule->GetObjectTypeCount();
for (uint32_t typeId = 0; typeId < typeCount; typeId++) {
@ -21,10 +26,9 @@ namespace Deer {
}
void Module::init() {
angelscriptModule->BindAllImportedFunctions();
if (invalidated)
if (state != ModuleState::Built)
return;
angelscriptModule->BindAllImportedFunctions();
for (Service& service : services)
service.init();
@ -34,7 +38,7 @@ namespace Deer {
}
void Module::update() {
if (invalidated)
if (state != ModuleState::Built)
return;
for (Service& service : services)
@ -45,7 +49,7 @@ namespace Deer {
}
void Module::render() {
if (invalidated)
if (state != ModuleState::Built)
return;
for (Panel& panel : panels)
@ -53,14 +57,14 @@ namespace Deer {
}
void Module::shutdown() {
if (state != ModuleState::Built)
return;
for (Service& service : services)
service.shutdown();
for (Panel& panel : panels)
panel.shutdown();
if (invalidated)
return;
}
Module::~Module() {

View File

@ -0,0 +1,17 @@
#pragma once
#include "DeerStudio/AngelScriptEngine.h"
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
namespace Deer {
namespace AngelScriptEngine {
template <class Archive>
void serialize(Archive& archive,
ModuleDescription& m) {
archive(cereal::make_nvp("name", m.moduleName));
archive(cereal::make_nvp("patch", m.patchVersion));
archive(cereal::make_nvp("requires", m.module_requires));
}
} // namespace AngelScriptEngine
} // namespace Deer

View File

@ -1,20 +1,28 @@
#include "DeerRender/Tools/Path.h"
#include "DeerStudio/AngelScriptEngine.h"
#include "DeerStudio/AngelScriptEngine/ErrorHandle.h"
#include "DeerStudio/AngelScriptEngine/ModuleDescriptorSerializer.h"
#include "angelscript.h"
#include "cereal/archives/json.hpp"
#include "scriptbuilder.h"
#include "DeerRender/Log.h"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>
namespace fs = std::filesystem;
namespace Deer {
namespace AngelScriptEngine {
void loadModule(const Path& path);
bool loadModule(Module& module);
void loadModuleInfo(const Path& path);
} // namespace AngelScriptEngine
asIScriptFunction* AngelScriptEngine::getFactory(asITypeInfo* type) {
@ -35,36 +43,116 @@ namespace Deer {
return type->GetFactoryByDecl(callString.c_str());
}
void AngelScriptEngine::loadModule(const Path& path) {
bool AngelScriptEngine::loadModule(Module& module) {
int err;
module.state = ModuleState::Building;
scriptBuilder.StartNewModule(scriptEngine, path.stem().string().c_str());
if (err < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed to init module for {0}", path.string().c_str());
return;
DEER_CORE_TRACE("Loading module {}", module.moduleInfo.moduleName);
for (const std::string& dependency : module.moduleInfo.module_requires) {
if (!module_id.contains(dependency)) {
DEER_CORE_ERROR("Failed to find dependency {} for module {}",
dependency.c_str(), module.moduleInfo.moduleName);
module.state = ModuleState::DependencyFailed;
return false;
}
for (const auto& entry : fs::recursive_directory_iterator(path)) {
Module& dependencyModule = modules[module_id[dependency]];
if (dependencyModule.state == ModuleState::DependencyFailed ||
dependencyModule.state == ModuleState::CompilationFailed) {
DEER_CORE_ERROR("Failed to load dependency {} for module {}, the dependency did not load correctly and caused a chain reaction",
dependency.c_str(), module.moduleInfo.moduleName.c_str());
module.state = ModuleState::DependencyFailed;
return false;
}
if (dependencyModule.state == ModuleState::Building) {
DEER_CORE_ERROR("Failed to load dependency {} for module {} due to loop",
dependency.c_str(), module.moduleInfo.moduleName.c_str());
module.state = ModuleState::DependencyFailed;
return false;
}
if (dependencyModule.state == ModuleState::NotBuilt) {
if (!loadModule(dependencyModule)) {
module.state = ModuleState::DependencyFailed;
return false;
}
}
}
scriptBuilder.StartNewModule(scriptEngine, module.moduleInfo.moduleName.c_str());
if (err < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed to init module for {0}", module.moduleInfo.moduleName.c_str());
module.state = ModuleState::CompilationFailed;
return false;
}
for (const auto& entry : fs::recursive_directory_iterator(module.moduleInfo.modulePath)) {
if (!entry.is_regular_file() || entry.path().extension() != ".as")
continue;
DEER_CORE_TRACE("{}", entry.path().filename().string().c_str());
err = scriptBuilder.AddSectionFromFile(entry.path().string().c_str());
if (err < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed loading script for module {0}\nscript: {1}", path.string().c_str(), entry.path().string().c_str());
DEER_EDITOR_ENGINE_ERROR("Failed loading script for module {0}\nscript: {1}", module.moduleInfo.moduleName.c_str(), entry.path().string().c_str());
module.state = ModuleState::CompilationFailed;
return false;
}
}
err = scriptBuilder.BuildModule();
asIScriptModule* module = scriptBuilder.GetModule();
asIScriptModule* as_module = scriptBuilder.GetModule();
if (err < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed compiling module {}\nerror: {}", path.stem().string().c_str(),
Deer::AngelScriptEngine::getAngelScriptReturnCodeString(err));
DEER_EDITOR_ENGINE_ERROR("Failed compiling module {}\nerror: {}", module.moduleInfo.moduleName.c_str(), Deer::AngelScriptEngine::getAngelScriptReturnCodeString(err));
module.state = ModuleState::CompilationFailed;
return false;
}
module.state = ModuleState::Built;
return true;
}
void AngelScriptEngine::loadModuleInfo(const Path& path) {
ModuleDescription desc;
std::ifstream is((path / "module.json").string());
if (!is.is_open()) {
DEER_CORE_ERROR("Cannot open module description: {}", (path / "module.json").string().c_str());
ModuleDescription desc;
desc.moduleName = path.stem().string();
desc.patchVersion = 1;
std::ofstream os((path / "module.json").string());
{
cereal::JSONOutputArchive archive(os);
serialize(archive, desc);
}
return;
}
modules.push_back({module});
std::string contents((std::istreambuf_iterator<char>(is)),
std::istreambuf_iterator<char>());
std::stringstream ss(contents);
try {
cereal::JSONInputArchive archive(ss);
serialize(archive, desc);
if (desc.moduleName.empty()) {
DEER_CORE_ERROR("Module description missing 'name' field: {}", path.string().c_str());
return;
}
if (desc.patchVersion < 0) {
DEER_CORE_ERROR("Module description missing 'name' field: {}", path.string().c_str());
return;
}
} catch (const std::exception& e) {
DEER_CORE_ERROR("Module description missing 'name' field: {}", path.string().c_str());
return;
}
desc.modulePath = path.string();
module_id[desc.moduleName] = modules.size();
modules.push_back({desc});
}
void AngelScriptEngine::loadModules() {
@ -77,14 +165,22 @@ namespace Deer {
}
for (const auto& module : fs::directory_iterator(path)) {
// saveAngelscriptPredefined(_dir);
if (module.path().extension() == ".disabled") {
DEER_CORE_TRACE("Ignoring {}", module.path().stem().string().c_str());
DEER_CORE_WARN("Ignoring {}", module.path().stem().string().c_str());
continue;
}
DEER_CORE_TRACE("=== Loading module {} ===", module.path().stem().string().c_str());
saveAngelscriptPredefined(module.path());
loadModule(module.path());
loadModuleInfo(module.path());
}
for (Module& module : modules) {
saveAngelscriptPredefined(module.moduleInfo.modulePath);
if (module.state == ModuleState::NotBuilt) {
loadModule(module);
}
}
for (Module& module : modules) {
module.extractTypes();
}
}
} // namespace Deer

View File

@ -17,7 +17,6 @@ namespace Deer {
Scope<MeshData> StorageData::deserialize<EditorDataImporter, MeshData>() {
Assimp::Importer importer;
DEER_CORE_TRACE("Size {}", size);
std::string extension;
const char* extension_char = nullptr;
if (getMetadata().contains("dataId")) {

View File

@ -1,5 +1,5 @@
#include "DeerRender/Log.h"
#include "DeerStudio/EditorDataSource.h"
#include "DeerRender/Log.h"
#include <fstream>
#include <sstream>
@ -8,6 +8,11 @@
namespace Deer {
StorageData StorageBackend<EditorDataSource>::loadData(const std::string& location) {
Path path = Path("Editor") / location;
if (!std::filesystem::exists(path)) {
return StorageData();
}
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open()) {
DEER_CORE_ERROR("Failed to open file '{}'", location.c_str());

View File

@ -1,5 +1,5 @@
#include "DeerRender/Log.h"
#include "DeerStudio/ResourceDataSource.h"
#include "DeerRender/Log.h"
#include <fstream>
#include <sstream>
@ -55,6 +55,10 @@ namespace Deer {
Path path = Path("Resources") / (location + ".meta");
StorageMetadata metadata;
if (!std::filesystem::exists(path)) {
return metadata;
}
std::ifstream file(path);
if (!file.is_open()) {
DEER_CORE_TRACE("Failed to open metadata file '{}' for reading", path.string().c_str());

View File

@ -241,7 +241,6 @@ namespace Deer {
EntityHandleStruct EntityStruct::createChild(std::string& name) {
ASSERT_ENTITY("createChild()", return *this);
DEER_CORE_INFO("Creating child on env {}", environmentId);
Environment* entityEnv = getEntityEnvironment();
Entity& newEnt = entityEnv->createEntity(name);

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "ActiveEntity",
"requires": []
}

View File

@ -0,0 +1,5 @@
{
"name": "EntityManipulation",
"patch": 1,
"requires": ["ActiveEntity"]
}

View File

@ -22,7 +22,6 @@ class RenderService : Service {
shaderC.shader = Resource::loadShader("shader.glsl");
Engine::print("CAM : " + sceneCamera.transform.position.x + " " + sceneCamera.transform.scale.x + " : " + sceneCamera.camera.aspect);
sceneCamera.transform.position.z = -3;
sceneCamera.transform.position.y = 1;

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "Previewer",
"requires": []
}

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "ResourceExplorer",
"requires": ["Previewer"]
}

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "TreeExplorer",
"requires": ["ActiveEntity"]
}

View File

@ -0,0 +1,5 @@
{
"patch": 1,
"name": "Viewport",
"requires": ["Previewer"]
}