Cleaning Obsolete Script Engine Editor

This commit is contained in:
Chewico 2025-12-04 22:38:49 +01:00
parent 64ce11080e
commit 23989d5cf7
22 changed files with 0 additions and 1555 deletions

View File

@ -1,89 +0,0 @@
#include "DeerStudio/DockPanel/DockPanelContext.h"
#include "DeerRender/Log.h"
#include "DeerStudio/EditorEngine.h"
#include "angelscript.h"
#include <stdint.h>
namespace Deer {
namespace StudioAPI {
DockPanelContext::DockPanelContext(asIScriptModule* _module, DockPanelInfo* _info)
: module(_module), info(_info) {
_module->BindAllImportedFunctions();
size_t nScripts = module->GetObjectTypeCount();
asITypeInfo* dockPanelType = scriptEngine->GetTypeInfoByName("DockPanel");
if (!dockPanelType) {
DEER_EDITOR_ENGINE_ERROR(
"Could not load DockPanel interface type");
return;
}
context = scriptEngine->CreateContext();
context->AddRef();
for (size_t i = 0; i < nScripts; i++) {
asITypeInfo* info = module->GetObjectTypeByIndex(i);
// If it does not implement dock panel we are not interested int
// it
if (!info->Implements(dockPanelType))
continue;
dockPanels.push_back({info, context});
}
}
DockPanelContext::DockPanelContext(DockPanelContext&& dp)
: dockPanels(std::move(dp.dockPanels)) {
module = dp.module;
context = dp.context;
info = dp.info;
dp.context = nullptr;
dp.module = nullptr;
dp.info = nullptr;
}
DockPanelContext& DockPanelContext::operator=(DockPanelContext&& dp) {
if (&dp != this) {
dockPanels = std::move(dp.dockPanels);
module = dp.module;
context = dp.context;
info = dp.info;
dp.context = nullptr;
dp.module = nullptr;
dp.info = nullptr;
}
return *this;
}
void DockPanelContext::init() {
for (DockPanelObject& panel : dockPanels) {
currentDockPanelExecution = &panel;
panel.init();
}
currentDockPanelExecution = nullptr;
}
void DockPanelContext::render() {
for (DockPanelObject& panel : dockPanels) {
currentDockPanelExecution = &panel;
panel.render();
}
currentDockPanelExecution = nullptr;
}
DockPanelContext::~DockPanelContext() {
dockPanels.clear();
if (context)
context->Release();
delete info;
}
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,39 +0,0 @@
#pragma once
#include "DockPanelInfo.h"
#include "DockPanelObject.h"
#include "DeerRender/Tools/Memory.h"
#include <string>
#include <vector>
class asIScriptModule;
class asIScriptContext;
namespace Deer {
namespace StudioAPI {
class DockPanelContext {
public:
DockPanelContext(asIScriptModule*, DockPanelInfo*);
~DockPanelContext();
DockPanelContext(DockPanelContext&) = delete;
DockPanelContext& operator=(DockPanelContext&) = delete;
DockPanelContext(DockPanelContext&&);
DockPanelContext& operator=(DockPanelContext&&);
void render();
void init();
inline const char* getName() const { return info->name.c_str(); }
std::vector<DockPanelObject> dockPanels;
private:
asIScriptContext* context;
asIScriptModule* module;
DockPanelInfo* info;
};
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,19 +0,0 @@
#pragma once
#include "DeerStudio/ServiceScript/ServiceScriptInfo.h"
#include "DeerRender/Tools/Path.h"
#include <string>
#include <vector>
namespace Deer {
namespace StudioAPI {
struct DockPanelInfo {
std::string name = "null";
std::string author = "";
std::string version = "0.0.0";
std::vector<ServiceScriptRef> services;
};
DockPanelInfo* loadDockPanelInfo(Path panelInfo);
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,49 +0,0 @@
#include "DeerRender/Log.h"
#include "DeerStudio/DockPanel/DockPanelInfo.h"
#include "cereal/archives/json.hpp"
#include "cereal/cereal.hpp"
#include "cereal/types/string.hpp"
#include "cereal/types/vector.hpp"
#include <cstring>
#include <filesystem>
#include <fstream>
namespace Deer {
namespace StudioAPI {
template <class Archive>
void serialize(Archive& ar, DockPanelInfo& data) {
ar(cereal::make_nvp("name", data.name));
ar(cereal::make_nvp("author", data.author));
ar(cereal::make_nvp("version", data.version));
ar(cereal::make_nvp("services", data.services));
}
template <class Archive>
void serialize(Archive& ar, ServiceScriptRef& data) {
ar(cereal::make_nvp("name", data.name));
ar(cereal::make_nvp("version", data.version));
}
DockPanelInfo* loadDockPanelInfo(Path dockPanelInfoPath) {
try {
std::ifstream is(dockPanelInfoPath);
if (!is)
return new DockPanelInfo();
DockPanelInfo* info = new DockPanelInfo();
{
cereal::JSONInputArchive archive(is);
archive(cereal::make_nvp("dockPanelModule", *info));
}
return info;
} catch (const std::exception& e) {
DEER_EDITOR_ENGINE_TRACE(e.what());
return new DockPanelInfo();
}
}
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,213 +0,0 @@
#include "DeerStudio/DockPanel/DockPanelObject.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerRender/Log.h"
#include "angelscript.h"
#include <string>
#include "imgui.h"
namespace Deer {
EditorEngine::DockPanelObject::DockPanelObject(
asITypeInfo* _type, asIScriptContext* _scriptContext)
: type(_type), isValid(false), scriptContext(_scriptContext) {
// Constructor
// "type@ type()"
std::string callString;
const std::string ns(type->GetNamespace());
if (ns != "") {
callString += ns;
callString += "::";
}
callString += type->GetName();
callString += "@ ";
if (ns != "") {
callString += ns;
callString += "::";
}
callString += type->GetName();
callString += "()";
flags = DockPanelFlag_ShowPanel;
asIScriptFunction* factory = type->GetFactoryByDecl(callString.c_str());
AS_CHECK(scriptContext->Prepare(factory));
AS_CHECK(scriptContext->Execute());
// Return value contains the ref to a asIScriptObject in the location
// provided
object = *(asIScriptObject**)scriptContext->GetAddressOfReturnValue();
if (!object) {
DEER_EDITOR_ENGINE_ERROR("Could not create object",
type->GetName());
return;
}
object->AddRef();
renderFunction = type->GetMethodByDecl("void onRender()");
if (!renderFunction) {
DEER_EDITOR_ENGINE_ERROR("Could not load void onRender() from {0}",
type->GetName());
return;
}
menuBarFunction = type->GetMethodByDecl("void onMenuBar()");
initFunction = type->GetMethodByDecl("void onInit()");
isValid = true;
scriptContext->Unprepare();
}
int EditorEngine::DockPanelObject::getRefCount() {
int refCount = object->AddRef(); // increments refcount by 1
refCount = object->Release();
return refCount;
}
const char* EditorEngine::DockPanelObject::getName() {
return type->GetName();
}
EditorEngine::DockPanelObject::~DockPanelObject() {
if (object)
object->Release();
}
void EditorEngine::DockPanelObject::invalidate() {
DEER_EDITOR_ENGINE_ERROR("Last error was caused executing {0}",
type->GetName());
isValid = false;
}
void EditorEngine::DockPanelObject::init() {
if (!initFunction)
return;
scriptContext = scriptContext;
AS_CHECK(scriptContext->Prepare(initFunction));
AS_CHECK(scriptContext->SetObject(object));
AS_CHECK(scriptContext->Execute());
AS_CHECK(scriptContext->Unprepare());
scriptContext = nullptr;
}
void EditorEngine::DockPanelObject::render() {
bool show = flags & DockPanelFlag_ShowPanel;
if (!show)
return;
// We cache the result because the user can remove the flag while
// executing
bool hasPadding = flags & DockPanelFlag_PanelPadding;
if (hasPadding)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
if (menuBarFunction) {
ImGui::Begin(type->GetName(), (bool*)0, ImGuiWindowFlags_MenuBar);
if (ImGui::BeginMenuBar()) {
scriptContext = scriptContext;
AS_CHECK(scriptContext->Prepare(menuBarFunction));
AS_CHECK(scriptContext->SetObject(object));
AS_CHECK(scriptContext->Execute());
AS_CHECK(scriptContext->Unprepare());
scriptContext = nullptr;
ImGui::EndMenuBar();
}
} else {
ImGui::Begin(type->GetName());
}
// This is to make sure that right click activates the window
if (ImGui::IsWindowHovered(
ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) &&
(ImGui::IsMouseClicked(ImGuiMouseButton_Right) ||
ImGui::IsMouseClicked(ImGuiMouseButton_Middle))) {
ImGui::SetWindowFocus();
}
if (!isValid) {
ImGui::TextColored(ImVec4(1, 0.3f, 0.3f, 1),
"There was a runtime error");
ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1),
"Please check the log");
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1),
"Plese restart the interface");
ImGui::End();
return;
}
scriptContext = scriptContext;
AS_CHECK(scriptContext->Prepare(renderFunction));
AS_CHECK(scriptContext->SetObject(object));
AS_CHECK(scriptContext->Execute());
AS_CHECK(scriptContext->Unprepare());
scriptContext = nullptr;
ImGui::End();
if (hasPadding)
ImGui::PopStyleVar();
}
EditorEngine::DockPanelObject::DockPanelObject(
DockPanelObject&& other) noexcept
: isValid(other.isValid), renderFunction(other.renderFunction),
type(other.type), object(other.object),
menuBarFunction(other.menuBarFunction),
initFunction(other.initFunction), flags(other.flags),
scriptContext(other.scriptContext) {
other.isValid = false;
other.renderFunction = nullptr;
other.type = nullptr;
other.object = nullptr;
other.menuBarFunction = nullptr;
other.initFunction = nullptr;
other.scriptContext = nullptr;
}
EditorEngine::DockPanelObject& EditorEngine::DockPanelObject::operator=(
EditorEngine::DockPanelObject&& other) noexcept {
if (this != &other) {
if (object)
object->Release();
isValid = other.isValid;
renderFunction = other.renderFunction;
type = other.type;
object = other.object;
menuBarFunction = other.menuBarFunction;
initFunction = other.initFunction;
flags = other.flags;
scriptContext = other.scriptContext;
other.isValid = false;
other.renderFunction = nullptr;
other.type = nullptr;
other.object = nullptr;
other.menuBarFunction = nullptr;
other.initFunction = nullptr;
other.scriptContext = nullptr;
}
return *this;
}
void EditorEngine::DockPanelObject::setFlag(uint32_t flag, bool value) {
if ((flag & flags) != value)
flags ^= flag;
}
bool EditorEngine::DockPanelObject::getFlag(uint32_t flag) {
return flag & flags;
}
} // namespace Deer

View File

@ -1,51 +0,0 @@
#pragma once
#include <stdint.h>
class asITypeInfo;
class asIScriptObject;
class asIScriptFunction;
class asIScriptContext;
namespace Deer {
namespace StudioAPI {
struct DockPanelObject {
private:
asITypeInfo* type = nullptr;
asIScriptObject* object = nullptr;
asIScriptFunction* renderFunction = nullptr;
asIScriptFunction* menuBarFunction = nullptr;
asIScriptFunction* initFunction = nullptr;
asIScriptContext* scriptContext = nullptr;
bool isValid = false;
uint32_t flags = 0;
public:
DockPanelObject(asITypeInfo*, asIScriptContext*);
~DockPanelObject();
// Delete copy constructor
DockPanelObject(const DockPanelObject&) = delete;
DockPanelObject& operator=(const DockPanelObject&) = delete;
DockPanelObject(DockPanelObject&& other) noexcept;
DockPanelObject& operator=(DockPanelObject&& other) noexcept;
void setFlag(uint32_t, bool);
bool getFlag(uint32_t);
void invalidate();
void init();
void render();
// TMP
int getRefCount();
const char* getName();
};
} // namespace StudioAPI
enum DockPanelFlags {
DockPanelFlag_PanelPadding = 1 << 0,
DockPanelFlag_ShowPanel = 1 << 1
};
} // namespace Deer

View File

@ -1,112 +0,0 @@
#include "DeerRender/Log.h"
#include "DeerStudio/DockPanel/DockPanelContext.h"
#include "DeerStudio/DockPanel/DockPanelInfo.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerStudio/EditorEngine/AngelscriptPredefined.h"
#include "DeerStudio/ServiceScript/ServiceScriptContext.h"
#include "DeerRender/DataStore.h"
#include "DeerRender/Tools/Path.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
namespace fs = std::filesystem;
namespace Deer {
namespace StudioAPI {
CScriptBuilder scriptBuilder;
ServiceScriptContext*
getServiceScriptContext(const ServiceScriptRef& ref) {
for (ServiceScriptContext& ctx : serviceScriptModules) {
const ServiceScriptInfo& info = ctx.getInfo();
if (info.name == ref.name && info.version == ref.version) {
return &ctx;
}
}
return nullptr;
}
} // namespace StudioAPI
void EditorEngine::loadDockPanels() {
Path path = DEER_EDITOR_PANEL_PATH;
if (!fs::exists(path) || !fs::is_directory(path)) {
DEER_EDITOR_ENGINE_ERROR(
"Could not find folder " DEER_EDITOR_PANEL_PATH);
return;
}
for (const auto& _dir : fs::directory_iterator(path)) {
Path panelInfo_path = _dir.path() / "dockPanelModule.json";
// A panel info is neded to load a panel
if (!fs::exists(panelInfo_path) ||
!fs::is_regular_file(panelInfo_path)) {
DEER_EDITOR_ENGINE_WARN("Editor engine did not find "
"dockPanelModule.json in folder {0}",
panelInfo_path.c_str());
continue;
}
DockPanelInfo* dockPanelInfo = loadDockPanelInfo(panelInfo_path);
if (dockPanelInfo->name == "null") {
DEER_EDITOR_ENGINE_ERROR(
"Failed to load dock panel module from {0},\n incorrect "
"panelInfo.json file",
path.string().c_str());
delete dockPanelInfo;
continue;
}
saveAngelscriptPredefined(_dir);
int r;
r = scriptBuilder.StartNewModule(scriptEngine, dockPanelInfo->name.c_str());
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR(
"Failed to create module for dock panel module {0}",
path.string().c_str());
delete dockPanelInfo;
continue;
}
asIScriptModule* module = scriptBuilder.GetModule();
for (const auto& entry : fs::recursive_directory_iterator(_dir)) {
if (entry.is_regular_file() &&
entry.path().extension() == ".as") {
r = scriptBuilder.AddSectionFromFile(
entry.path().string().c_str());
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR(
"Failed loading script for module {0}\nscript: {1}",
path.string().c_str(),
entry.path().string().c_str());
}
}
}
r = scriptBuilder.BuildModule();
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed compiling module {0}",
_dir.path().stem().string().c_str());
delete dockPanelInfo;
continue;
}
DEER_CORE_TRACE("Loaded dock panel {}", dockPanelInfo->name.c_str());
dockPanelModules.push_back({module, dockPanelInfo});
}
}
} // namespace Deer

View File

@ -1,12 +0,0 @@
#pragma once
#include "DeerStudio/StudioAPI/Debug.h"
#include "DeerStudio/StudioAPI/Engine.h"
#include "DeerStudio/StudioAPI/Entity.h"
#include "DeerStudio/StudioAPI/Environment.h"
#include "DeerStudio/StudioAPI/FrameBuffer.h"
#include "DeerStudio/StudioAPI/Layout.h"
#include "DeerStudio/StudioAPI/Math.h"
#include "DeerStudio/StudioAPI/Menu.h"
#include "DeerStudio/StudioAPI/Resources.h"
#include "DeerStudio/StudioAPI/UI.h"

View File

@ -1,243 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// THIS FILE IS A MODIFIED VERSION
// https://github.com/sashi0034/angel-lsp/blob/main/examples/OpenSiv3D/make_predefined.cpp
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "DeerStudio/EditorEngine/AngelscriptPredefined.h"
#include "DeerStudio/AngelScriptEngine.h"
#include "DeerStudio/EditorEngine.h"
#include "angelscript.h"
#include <iso646.h>
#include <sstream>
#include <string>
#include <string_view>
#include <angelscript.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <string_view>
#include "DeerRender/DataStore.h"
#include "DeerRender/Tools/Path.h"
static std::stringstream stream;
static std::string str;
void printFuncList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetFuncdefCount(); ++i) {
asITypeInfo* t = engine.GetFuncdefByIndex(i);
if (!t)
continue;
asIScriptFunction* func = t->GetFuncdefSignature();
if (!func || func->GetSubType())
continue;
std::string decl = func->GetDeclaration(true, true, true);
// Detect class-scoped funcdefs by presence of "::" in the declaration
size_t scopePos = decl.find("::");
if (scopePos != std::string::npos)
continue;
stream << "funcdef " << decl << ";\n";
}
}
void printEnumList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetEnumCount(); ++i) {
const auto e = engine.GetEnumByIndex(i);
if (!e)
continue;
std::string_view ns = e->GetNamespace();
if (!ns.empty())
stream << "namespace " << ns << " {\n";
stream << "enum " << e->GetName() << " {\n";
for (int j = 0; j < e->GetEnumValueCount(); ++j) {
int value;
stream << "\t" << e->GetEnumValueByIndex(j, &value) << " = "
<< value;
if (j < e->GetEnumValueCount() - 1)
stream << ",";
stream << "\n";
}
stream << "}\n";
if (!ns.empty())
stream << "}\n\n";
}
}
void printClassTypeList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetObjectTypeCount(); ++i) {
asITypeInfo* t = engine.GetObjectTypeByIndex(i);
if (!t)
continue;
std::string_view ns = t->GetNamespace();
if (!ns.empty())
stream << "namespace " << ns << " {\n";
stream << "class " << t->GetName();
if (std::string("any") == t->GetName())
stream << " ";
if (t->GetSubTypeCount() > 0) {
stream << "<";
for (int sub = 0; sub < t->GetSubTypeCount(); ++sub) {
if (sub > 0)
stream << ", ";
const auto st = t->GetSubType(sub);
stream << st->GetName();
}
stream << ">";
}
stream << " {\n";
for (int i = 0; i < t->GetChildFuncdefCount(); ++i) {
asITypeInfo* ftype = t->GetChildFuncdef(i);
asIScriptFunction* func = ftype->GetFuncdefSignature();
std::string decl = func->GetDeclaration(false, false, true);
stream << "\tfuncdef " << decl << ";\n";
}
for (int j = 0; j < t->GetFactoryCount(); ++j) {
asIScriptFunction* f = t->GetFactoryByIndex(j);
stream << "\t" << f->GetDeclaration(false, false, true) << ";\n";
}
for (int j = 0; j < t->GetBehaviourCount(); ++j) {
asEBehaviours behaviours;
const auto f = t->GetBehaviourByIndex(j, &behaviours);
if (behaviours == asBEHAVE_CONSTRUCT ||
behaviours == asBEHAVE_DESTRUCT ||
behaviours == asBEHAVE_FACTORY)
stream << "\t" << f->GetDeclaration(false, false, true)
<< ";\n";
}
for (int j = 0; j < t->GetMethodCount(); ++j) {
const auto m = t->GetMethodByIndex(j);
stream << "\t" << m->GetDeclaration(false, false, true);
if (m->IsProperty())
stream << " property";
stream << ";\n";
}
for (int j = 0; j < t->GetPropertyCount(); ++j) {
stream << "\t" << t->GetPropertyDeclaration(j, false) << ";\n";
}
for (int j = 0; j < t->GetChildFuncdefCount(); ++j) {
stream
<< "\tfuncdef "
<< t->GetChildFuncdef(j)->GetFuncdefSignature()->GetDeclaration(
false)
<< ";\n";
}
stream << "}\n";
if (!ns.empty())
stream << "}\n\n";
}
}
void printGlobalFunctionList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetGlobalFunctionCount(); ++i) {
const auto f = engine.GetGlobalFunctionByIndex(i);
if (!f)
continue;
std::string_view ns = f->GetNamespace();
if (!ns.empty())
stream << "namespace " << ns << " { ";
stream << f->GetDeclaration(false, false, true) << ";";
if (!ns.empty())
stream << " }";
stream << "\n";
}
}
void printGlobalPropertyList(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetGlobalPropertyCount(); ++i) {
const char* name;
const char* ns0;
int type;
engine.GetGlobalPropertyByIndex(i, &name, &ns0, &type, nullptr, nullptr,
nullptr, nullptr);
std::string t = engine.GetTypeDeclaration(type, true);
if (t.empty())
continue;
std::string_view ns = ns0;
if (!ns.empty())
stream << "namespace " << ns << " { ";
stream << t << " " << name << ";";
if (!ns.empty())
stream << " }";
stream << "\n";
}
}
void printGlobalTypedef(const asIScriptEngine& engine) {
for (int i = 0; i < engine.GetTypedefCount(); ++i) {
const auto type = engine.GetTypedefByIndex(i);
if (!type)
continue;
std::string_view ns = type->GetNamespace();
if (!ns.empty())
stream << "namespace " << ns << " {\n";
stream << "typedef "
<< engine.GetTypeDeclaration(type->GetTypedefTypeId()) << " "
<< type->GetName() << ";\n";
if (!ns.empty())
stream << "}\n";
}
}
void printAngelInfo(const asIScriptEngine& engine) {
printFuncList(engine);
printEnumList(engine);
printClassTypeList(engine);
printGlobalFunctionList(engine);
printGlobalPropertyList(engine);
printGlobalTypedef(engine);
}
namespace Deer {
void AngelScriptEngine::generateAngelscriptPredefined() {
stream.clear();
stream << "//This file was generated automatically\n";
printAngelInfo(*Deer::AngelScriptEngine::scriptEngine);
str = stream.str();
}
void AngelScriptEngine::saveAngelscriptPredefined(const Path& path) {
Deer::Path filePath = path / "as.predefined";
std::ofstream file(filePath, std::ios::out | std::ios::binary);
file.write(reinterpret_cast<const char*>(str.c_str()), str.size());
file.close();
}
} // namespace Deer

View File

@ -1,9 +0,0 @@
#pragma once
#include "DeerRender/Tools/Path.h"
namespace Deer {
namespace AngelScriptEngine {
void generateAngelscriptPredefined();
void saveAngelscriptPredefined(const Path& path);
} // namespace AngelScriptEngine
} // namespace Deer

View File

@ -1,82 +0,0 @@
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/API.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerRender/Log.h"
#include <vector>
#include "angelscript.h"
#include "scriptany.h"
#include "scriptarray.h"
#include "scriptbuilder.h"
#include "scriptdictionary.h"
#include "scripthandle.h"
#include "scriptstdstring.h"
namespace Deer {
namespace StudioAPI {
asIScriptEngine* scriptEngine = nullptr;
std::vector<DockPanelContext> dockPanelModules;
std::vector<ServiceScriptContext> serviceScriptModules;
DockPanelObject* currentDockPanelExecution = nullptr;
asIScriptContext* scriptContext;
bool active = false;
} // namespace StudioAPI
void EditorEngine::initialize() {
int err = 0;
// If it exist we will reload it
deinitialize();
scriptEngine = asCreateScriptEngine();
AS_RET_CHECK(scriptEngine->SetMessageCallback(asFUNCTION(Deer::EditorEngine::errorCallback), 0, asCALL_CDECL));
RegisterScriptHandle(scriptEngine);
RegisterScriptAny(scriptEngine);
RegisterStdString(scriptEngine);
RegisterScriptArray(scriptEngine, true);
RegisterScriptDictionary(scriptEngine);
registerEditorEngineStructs();
registerEditorEngineFunctions();
// We generate a as.predefined file generic for services
generateAngelscriptPredefined();
loadServiceScripts();
generateAngelscriptPredefined();
loadDockPanels();
active = true;
for (ServiceScriptContext& service : serviceScriptModules) {
service.init();
}
for (DockPanelContext& panel : dockPanelModules)
panel.init();
}
void EditorEngine::deinitialize() {
dockPanelModules.clear();
serviceScriptModules.clear();
if (scriptEngine)
scriptEngine->ShutDownAndRelease();
scriptEngine = nullptr;
active = false;
}
void EditorEngine::render() {
if (!active)
return;
for (auto& panel : dockPanelModules)
panel.render();
}
} // namespace Deer

View File

@ -1,36 +0,0 @@
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "angelscript.h"
namespace Deer {
namespace StudioAPI {
const char* getAngelScriptReturnCodeString(int code)
{
switch (code)
{
case asSUCCESS: return "SUCCESS (The operation was successful)";
case asERROR: return "ERROR (A generic error occurred)";
case asCONTEXT_ACTIVE: return "CONTEXT_ACTIVE (A context was active during an invalid operation)";
case asCONTEXT_NOT_FINISHED: return "CONTEXT_NOT_FINISHED (Context has not finished execution)";
case asCONTEXT_NOT_PREPARED: return "CONTEXT_NOT_PREPARED (Context is not prepared)";
case asINVALID_ARG: return "INVALID_ARG (An invalid argument was provided)";
case asNO_FUNCTION: return "NO_FUNCTION (Function not found)";
case asNOT_SUPPORTED: return "NOT_SUPPORTED (Feature not supported by build configuration)";
case asINVALID_NAME: return "INVALID_NAME (Name is not allowed or invalid)";
case asNAME_TAKEN: return "NAME_TAKEN (Name is already taken by another entity)";
case asINVALID_DECLARATION: return "INVALID_DECLARATION (The declaration is invalid)";
case asINVALID_OBJECT: return "INVALID_OBJECT (Invalid object handle or object type)";
case asINVALID_TYPE: return "INVALID_TYPE (Invalid type provided)";
case asALREADY_REGISTERED: return "ALREADY_REGISTERED (Item is already registered)";
case asMULTIPLE_FUNCTIONS: return "MULTIPLE_FUNCTIONS (More than one matching function found)";
case asNO_MODULE: return "NO_MODULE (Module was not found)";
case asNO_GLOBAL_VAR: return "NO_GLOBAL_VAR (Global variable was not found)";
case asINVALID_CONFIGURATION: return "INVALID_CONFIGURATION (Invalid configuration, likely during registration)";
case asINVALID_INTERFACE: return "INVALID_INTERFACE (Invalid interface registration)";
case asCANT_BIND_ALL_FUNCTIONS: return "CANT_BIND_ALL_FUNCTIONS (Couldn't bind all functions for a virtual interface)";
case asLOWER_ARRAY_DIMENSION_NOT_REGISTERED: return "LOWER_ARRAY_DIMENSION_NOT_REGISTERED (Lower dimension type for array not registered)";
default: return "Unknown AngelScript error code";
}
}
}
}

View File

@ -1,32 +0,0 @@
#pragma once
#include "DeerRender/Log.h"
#include "angelscript.h"
namespace Deer {
namespace StudioAPI {
const char* getAngelScriptReturnCodeString(int code);
}
} // namespace Deer
#define AS_CHECK(f) \
{ \
int __r = f; \
if (__r < 0) { \
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r)); \
} \
}
#define AS_CHECK_ADDITIONAL_INFO(f, i) \
{ \
int __r = f; \
if (__r < 0) { \
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2} \n {3}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r), i); \
} \
}
#define AS_RET_CHECK(f) \
{ \
int __r = f; \
if (__r < 0) { \
DEER_EDITOR_ENGINE_ERROR("Error at line: {0}:{1} -> {2}", __FILE__, __LINE__, Deer::EditorEngine::getAngelScriptReturnCodeString(__r)); \
return; \
} \
}

View File

@ -1,82 +0,0 @@
#include "DeerRender/Log.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/AngelscriptPredefined.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerStudio/ServiceScript/ServiceScriptContext.h"
#include "DeerStudio/ServiceScript/ServiceScriptInfo.h"
#include "DeerRender/DataStore.h"
#include "DeerRender/Tools/Path.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
namespace fs = std::filesystem;
namespace Deer {
void EditorEngine::loadServiceScripts() {
Path path = DEER_EDITOR_SERVICE_PATH;
if (!fs::exists(path) || !fs::is_directory(path)) {
DEER_EDITOR_ENGINE_ERROR(
"Could not find folder " DEER_EDITOR_SERVICE_PATH);
return;
}
for (const auto& _dir : fs::directory_iterator(path)) {
Path panelInfo_path = _dir.path() / "ServiceScript.json";
// A panel info is neded to load a panel
if (!fs::exists(panelInfo_path) ||
!fs::is_regular_file(panelInfo_path)) {
DEER_EDITOR_ENGINE_WARN("Editor engine did not find "
"ServiceScript.json in folder {0}",
panelInfo_path.c_str());
continue;
}
ServiceScriptInfo* serviceScriptInfo = loadServiceScriptInfo(panelInfo_path);
if (serviceScriptInfo->name == "null") {
DEER_EDITOR_ENGINE_ERROR("Failed to load service script module from {0},\n "
"incorrect ServiceScript.json file",
path.string().c_str());
delete serviceScriptInfo;
continue;
}
saveAngelscriptPredefined(_dir);
int r;
r = scriptBuilder.StartNewModule(scriptEngine, serviceScriptInfo->name.c_str());
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed to create module for service script module {0}", path.string().c_str());
delete serviceScriptInfo;
continue;
}
for (const auto& entry : fs::recursive_directory_iterator(_dir)) {
if (entry.is_regular_file() &&
entry.path().extension() == ".as") {
r = scriptBuilder.AddSectionFromFile(entry.path().string().c_str());
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed loading script for module {0}\nscript: {1}", path.string().c_str(), entry.path().string().c_str());
}
}
}
r = scriptBuilder.BuildModule();
if (r < 0) {
DEER_EDITOR_ENGINE_ERROR("Failed compiling module {0}", path.string().c_str());
delete serviceScriptInfo;
continue;
}
DEER_CORE_TRACE("Loaded service script {}", serviceScriptInfo->name.c_str());
serviceScriptModules.push_back(ServiceScriptContext(scriptEngine->GetModule(serviceScriptInfo->name.c_str()), serviceScriptInfo));
}
}
} // namespace Deer

View File

@ -1,41 +0,0 @@
#include "DeerRender/Log.h"
#include "DeerStudio/ServiceScript/ServiceScriptInfo.h"
#include "cereal/archives/json.hpp"
#include "cereal/cereal.hpp"
#include "cereal/types/string.hpp"
#include <cstring>
#include <filesystem>
#include <fstream>
namespace Deer {
namespace StudioAPI {
template <class Archive>
void serialize(Archive& ar, ServiceScriptInfo& data) {
ar(cereal::make_nvp("name", data.name));
ar(cereal::make_nvp("author", data.author));
ar(cereal::make_nvp("version", data.version));
}
ServiceScriptInfo* loadServiceScriptInfo(Path seriveScriptInfoPath) {
try {
std::ifstream is(seriveScriptInfoPath);
if (!is)
return new ServiceScriptInfo();
ServiceScriptInfo* info = new ServiceScriptInfo();
{
cereal::JSONInputArchive archive(is);
archive(cereal::make_nvp("serviceScriptModule", *info));
}
return info;
} catch (const std::exception& e) {
DEER_EDITOR_ENGINE_TRACE(e.what());
return new ServiceScriptInfo();
}
}
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,86 +0,0 @@
#include "DeerStudio/ServiceScript/ServiceScriptContext.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "angelscript.h"
namespace Deer {
namespace StudioAPI {
ServiceScriptContext::ServiceScriptContext(asIScriptModule* _module,
ServiceScriptInfo* _info)
: info(_info), module(_module) {
size_t nScripts = module->GetObjectTypeCount();
asITypeInfo* serviceScriptType =
scriptEngine->GetTypeInfoByName("ServiceScript");
if (!serviceScriptType) {
DEER_EDITOR_ENGINE_ERROR(
"Could not load ServiceScript interface type");
return;
}
context = scriptEngine->CreateContext();
context->AddRef();
for (size_t i = 0; i < nScripts; i++) {
asITypeInfo* info = module->GetObjectTypeByIndex(i);
// If it does not implement service script we are not interested
// int it
if (!info->Implements(serviceScriptType))
continue;
scriptServices.push_back({info, context});
}
}
ServiceScriptContext::~ServiceScriptContext() {
scriptServices.clear();
if (context)
context->Release();
delete info;
}
ServiceScriptContext::ServiceScriptContext(ServiceScriptContext&& o)
: scriptServices(std::move(o.scriptServices)) {
context = o.context;
module = o.module;
info = o.info;
module->LoadByteCode()
o.context = nullptr;
o.module = nullptr;
o.info = nullptr;
}
ServiceScriptContext&
ServiceScriptContext::operator=(ServiceScriptContext&& o) {
if (&o != this) {
scriptServices = std::move(o.scriptServices);
context = o.context;
module = o.module;
info = o.info;
o.context = nullptr;
o.module = nullptr;
o.info = nullptr;
}
return *this;
}
void ServiceScriptContext::update() {
for (auto& scriptService : scriptServices) {
scriptService.update();
}
}
void ServiceScriptContext::init() {
for (auto& scriptService : scriptServices) {
scriptService.init();
}
}
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,36 +0,0 @@
#pragma once
#include "DeerStudio/ServiceScript/ServiceScriptInfo.h"
#include "DeerStudio/ServiceScript/ServiceScriptObject.h"
#include <vector>
class asIScriptModule;
class asIScriptContext;
namespace Deer {
namespace StudioAPI {
class ServiceScriptContext {
public:
ServiceScriptContext(asIScriptModule*, ServiceScriptInfo*);
~ServiceScriptContext();
ServiceScriptContext(ServiceScriptContext&) = delete;
ServiceScriptContext& operator=(ServiceScriptContext&) = delete;
ServiceScriptContext(ServiceScriptContext&&);
ServiceScriptContext& operator=(ServiceScriptContext&&);
void update();
void init();
inline const char* getName() const { return info->name.c_str(); }
inline const ServiceScriptInfo& getInfo() const { return *info; }
std::vector<ServiceScriptObject> scriptServices;
private:
asIScriptContext* context;
asIScriptModule* module;
ServiceScriptInfo* info;
};
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,127 +0,0 @@
#include "ServiceScriptGenericFunction.h"
#include "DeerRender/Log.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "angelscript.h"
namespace Deer {
bool copyParameter(asIScriptContext* ctx, int paramIndex, int typeId,
asDWORD flags, asIScriptGeneric* gen);
bool copyReturnValue(asIScriptGeneric* gen, asIScriptContext* ctx,
asIScriptFunction* func);
void EditorEngine::apiFunction(asIScriptGeneric* func) {
ServiceScriptFunction* serviceScriptFunction =
(ServiceScriptFunction*)func->GetAuxiliary();
asIScriptContext* context = serviceScriptFunction->scriptContext;
asIScriptFunction* apiFunction = serviceScriptFunction->apiFunction;
DEER_CORE_ASSERT(context, "Nullptr service script context calling {0}",
func->GetFunction()->GetDeclaration());
AS_CHECK(context->Prepare(apiFunction));
AS_CHECK(context->SetObject(serviceScriptFunction->scriptObject));
// Extract atributes
asUINT paramCount = apiFunction->GetParamCount();
for (asUINT i = 0; i < paramCount; i++) {
int type;
asDWORD flags;
apiFunction->GetParam(i, &type, &flags, nullptr);
copyParameter(context, i, type, flags, func);
}
AS_CHECK(context->Execute());
copyReturnValue(func, context, apiFunction);
AS_CHECK(context->Unprepare());
}
bool copyParameter(asIScriptContext* ctx, int paramIndex, int typeId,
asDWORD flags, asIScriptGeneric* gen) {
if (flags & asTM_OUTREF) {
// Skip out refs for now
// Unsupported type
DEER_EDITOR_ENGINE_WARN(
"Skipping our ref type {0} when calling {1}",
ctx->GetEngine()->GetTypeDeclaration(typeId, true),
gen->GetFunction()->GetDeclaration());
return false;
}
if (typeId == asTYPEID_INT32) {
ctx->SetArgDWord(paramIndex, gen->GetArgDWord(paramIndex));
} else if (typeId == asTYPEID_FLOAT) {
ctx->SetArgFloat(paramIndex, gen->GetArgFloat(paramIndex));
} else if (typeId == asTYPEID_DOUBLE) {
ctx->SetArgDouble(paramIndex, gen->GetArgDouble(paramIndex));
} else if (typeId == asTYPEID_INT64) {
ctx->SetArgQWord(paramIndex, gen->GetArgQWord(paramIndex));
} else if (typeId & asTYPEID_OBJHANDLE) {
void* obj =
gen->GetArgAddress(paramIndex); // Use GetArgAddress instead of
// GetArgObject for handles
ctx->SetArgObject(paramIndex, obj);
} else if (typeId & asTYPEID_MASK_OBJECT) {
void* obj = gen->GetArgObject(paramIndex);
ctx->SetArgObject(paramIndex, obj);
} else {
// Unsupported type
DEER_EDITOR_ENGINE_WARN(
"Unsuported type {0} when calling {1}",
ctx->GetEngine()->GetTypeDeclaration(typeId, true),
gen->GetFunction()->GetDeclaration());
return false;
}
return true;
}
bool copyReturnValue(asIScriptGeneric* gen, asIScriptContext* ctx,
asIScriptFunction* func) {
int returnTypeId = func->GetReturnTypeId();
asITypeInfo* typeInfo = ctx->GetEngine()->GetTypeInfoById(returnTypeId);
if (returnTypeId == asTYPEID_VOID) {
// Nothing to return
return true;
}
if (returnTypeId == asTYPEID_INT32) {
gen->SetReturnDWord(ctx->GetReturnDWord());
} else if (returnTypeId == asTYPEID_FLOAT) {
gen->SetReturnFloat(ctx->GetReturnFloat());
} else if (returnTypeId == asTYPEID_DOUBLE) {
gen->SetReturnDouble(ctx->GetReturnDouble());
} else if (returnTypeId == asTYPEID_INT64) {
gen->SetReturnQWord(ctx->GetReturnQWord());
} else if (returnTypeId & asTYPEID_OBJHANDLE) {
void* obj = ctx->GetReturnAddress(); // For handles, this returns
// the pointer
gen->SetReturnAddress(obj);
} else if (returnTypeId & asTYPEID_MASK_OBJECT) {
bool isRef = (typeInfo->GetFlags() & asOBJ_REF) != 0;
if (isRef) {
void* obj = ctx->GetReturnObject();
gen->SetReturnObject(obj);
} else {
void* src = ctx->GetReturnObject();
void* dst = gen->GetAddressOfReturnLocation();
memcpy(dst, src, typeInfo->GetSize());
}
} else {
DEER_EDITOR_ENGINE_WARN(
"Unsupported return type {0} in call to {1}",
ctx->GetEngine()->GetTypeDeclaration(returnTypeId, true),
func->GetDeclaration());
return false;
}
return true;
}
} // namespace Deer

View File

@ -1,20 +0,0 @@
#pragma once
#include "angelscript.h"
class asIScriptGeneric;
class asIScriptFunction;
class asIScriptContext;
class asIScriptObject;
namespace Deer {
namespace StudioAPI {
struct ServiceScriptObject;
struct ServiceScriptFunction {
asIScriptFunction* apiFunction = nullptr;
asIScriptContext* scriptContext = nullptr;
asIScriptObject* scriptObject = nullptr;
};
void apiFunction(asIScriptGeneric* gen);
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,20 +0,0 @@
#pragma once
#include "DeerRender/Tools/Path.h"
#include <string>
namespace Deer {
namespace StudioAPI {
struct ServiceScriptInfo {
std::string name = "null";
std::string author = "";
std::string version = "0.0.0";
};
struct ServiceScriptRef {
std::string name = "";
std::string version = "0.0.0";
};
ServiceScriptInfo* loadServiceScriptInfo(Path panelInfo);
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,118 +0,0 @@
#include "DeerStudio/ServiceScript/ServiceScriptObject.h"
#include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "DeerStudio/ServiceScript/ServiceScriptGenericFunction.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include <functional>
#include <sstream>
#include <string>
namespace Deer {
namespace StudioAPI {
ServiceScriptObject::ServiceScriptObject(
asITypeInfo* _type, asIScriptContext* _scriptContext)
: type(_type), scriptContext(_scriptContext) {
// Constructor
// "type@ type()"
std::string callString;
const std::string ns(type->GetNamespace());
if (ns != "") {
callString += ns;
callString += "::";
}
callString += type->GetName();
callString += "@ ";
if (ns != "") {
callString += ns;
callString += "::";
}
callString += type->GetName();
callString += "()";
asIScriptFunction* factory =
type->GetFactoryByDecl(callString.c_str());
AS_CHECK(scriptContext->Prepare(factory));
AS_CHECK(scriptContext->Execute());
// Return value contains the ref to a asIScriptObject in the
// location provided
object =
*(asIScriptObject**)scriptContext->GetAddressOfReturnValue();
if (!object) {
DEER_EDITOR_ENGINE_ERROR("Could not create object",
type->GetName());
return;
}
object->AddRef();
updateFunction = type->GetMethodByDecl("void onUpdate()");
initFunction = type->GetMethodByDecl("void onInit()");
scriptContext->Unprepare();
}
ServiceScriptObject::~ServiceScriptObject() {
if (object)
object->Release();
}
void ServiceScriptObject::init() {
if (!initFunction)
return;
AS_CHECK(scriptContext->Prepare(initFunction));
AS_CHECK(scriptContext->SetObject(object));
AS_CHECK(scriptContext->Execute());
AS_CHECK(scriptContext->Unprepare());
}
void ServiceScriptObject::update() {
if (!updateFunction)
return;
AS_CHECK(scriptContext->Prepare(updateFunction));
AS_CHECK(scriptContext->SetObject(object));
AS_CHECK(scriptContext->Execute());
AS_CHECK(scriptContext->Unprepare());
}
ServiceScriptObject::ServiceScriptObject(
ServiceScriptObject&& other) noexcept {
type = other.type;
object = other.object;
updateFunction = other.updateFunction;
initFunction = other.initFunction;
scriptContext = other.scriptContext;
other.type = nullptr;
other.object = nullptr;
other.updateFunction = nullptr;
other.initFunction = nullptr;
other.scriptContext = nullptr;
}
ServiceScriptObject&
ServiceScriptObject::operator=(ServiceScriptObject&& other) noexcept {
if (&other != this) {
type = other.type;
object = other.object;
updateFunction = other.updateFunction;
initFunction = other.initFunction;
scriptContext = other.scriptContext;
other.type = nullptr;
other.object = nullptr;
other.updateFunction = nullptr;
other.initFunction = nullptr;
other.scriptContext = nullptr;
}
return *this;
}
} // namespace StudioAPI
} // namespace Deer

View File

@ -1,39 +0,0 @@
#pragma once
#include <stdint.h>
class asITypeInfo;
class asIScriptObject;
class asIScriptFunction;
class asIScriptContext;
class asIScriptGeneric;
class asIScriptModule;
namespace Deer {
namespace StudioAPI {
struct ServiceScriptObject {
public:
ServiceScriptObject(asITypeInfo*, asIScriptContext*);
~ServiceScriptObject();
// Delete copy constructor
ServiceScriptObject(const ServiceScriptObject&) = delete;
ServiceScriptObject&
operator=(const ServiceScriptObject&) = delete;
ServiceScriptObject(ServiceScriptObject&& other) noexcept;
ServiceScriptObject&
operator=(ServiceScriptObject&& other) noexcept;
void init();
void update();
const char* getName();
private:
asITypeInfo* type = nullptr;
asIScriptObject* object = nullptr;
asIScriptFunction* updateFunction = nullptr;
asIScriptFunction* initFunction = nullptr;
asIScriptContext* scriptContext = nullptr;
};
} // namespace StudioAPI
} // namespace Deer