Cleaning Obsolete Script Engine Editor
This commit is contained in:
parent
64ce11080e
commit
23989d5cf7
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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"
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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; \
|
||||
} \
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user