Compare commits

..

2 Commits

Author SHA1 Message Date
3cc97f579f GLUE for Service Script API 2025-06-24 19:02:27 +02:00
e83c55f0e4 Update GitHub Actions workflow to fix OpenGL dependencies 2025-06-23 16:30:31 +02:00
16 changed files with 208 additions and 89 deletions

View File

@ -16,3 +16,4 @@ BraceWrapping:
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false
BreakBeforeBraces: Attach BreakBeforeBraces: Attach
NamespaceIndentation: All NamespaceIndentation: All
PointerAlignment: Left

View File

@ -67,8 +67,8 @@ Size=104,68
Collapsed=0 Collapsed=0
[Window][Test] [Window][Test]
Pos=60,60 Pos=560,275
Size=55,82 Size=396,176
Collapsed=0 Collapsed=0
[Docking][Data] [Docking][Data]

View File

@ -1,10 +1,127 @@
#include "ServiceScriptGenericFunction.h" #include "ServiceScriptGenericFunction.h"
#include "Deer/Log.h" #include "Deer/Log.h"
#include "DeerStudio/EditorEngine/ErrorHandle.h"
#include "angelscript.h" #include "angelscript.h"
namespace Deer { namespace Deer {
void EditorEngine::apiFunction(asIScriptGeneric *func) { bool copyParameter(asIScriptContext* ctx, int paramIndex, int typeId,
DEER_CORE_TRACE("Called function {0}", asDWORD flags, asIScriptGeneric* gen);
func->GetFunction()->GetDeclaration()); 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 } // namespace Deer

View File

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

View File

@ -15,7 +15,7 @@
namespace Deer { namespace Deer {
namespace EditorEngine { namespace EditorEngine {
ServiceScriptObject::ServiceScriptObject( ServiceScriptObject::ServiceScriptObject(
asITypeInfo *_type, asIScriptContext *_scriptContext) asITypeInfo* _type, asIScriptContext* _scriptContext)
: type(_type), scriptContext(_scriptContext) { : type(_type), scriptContext(_scriptContext) {
// Constructor // Constructor
// "type@ type()" // "type@ type()"
@ -34,7 +34,7 @@ namespace Deer {
callString += type->GetName(); callString += type->GetName();
callString += "()"; callString += "()";
asIScriptFunction *factory = asIScriptFunction* factory =
type->GetFactoryByDecl(callString.c_str()); type->GetFactoryByDecl(callString.c_str());
AS_CHECK(scriptContext->Prepare(factory)); AS_CHECK(scriptContext->Prepare(factory));
@ -43,7 +43,7 @@ namespace Deer {
// Return value contains the ref to a asIScriptObject in the // Return value contains the ref to a asIScriptObject in the
// location provided // location provided
object = object =
*(asIScriptObject **)scriptContext->GetAddressOfReturnValue(); *(asIScriptObject**)scriptContext->GetAddressOfReturnValue();
if (!object) { if (!object) {
DEER_EDITOR_ENGINE_ERROR("Could not create object", DEER_EDITOR_ENGINE_ERROR("Could not create object",
type->GetName()); type->GetName());
@ -83,7 +83,7 @@ namespace Deer {
} }
ServiceScriptObject::ServiceScriptObject( ServiceScriptObject::ServiceScriptObject(
ServiceScriptObject &&other) noexcept { ServiceScriptObject&& other) noexcept {
type = other.type; type = other.type;
object = other.object; object = other.object;
updateFunction = other.updateFunction; updateFunction = other.updateFunction;
@ -97,8 +97,8 @@ namespace Deer {
other.scriptContext = nullptr; other.scriptContext = nullptr;
} }
ServiceScriptObject & ServiceScriptObject&
ServiceScriptObject::operator=(ServiceScriptObject &&other) noexcept { ServiceScriptObject::operator=(ServiceScriptObject&& other) noexcept {
if (&other != this) { if (&other != this) {
type = other.type; type = other.type;
object = other.object; object = other.object;
@ -117,13 +117,13 @@ namespace Deer {
void ServiceScriptObject::bindFunctions() { void ServiceScriptObject::bindFunctions() {
for (int i = 0; i < type->GetMethodCount(); i++) { for (int i = 0; i < type->GetMethodCount(); i++) {
asIScriptFunction *func = type->GetMethodByIndex(i); asIScriptFunction* func = type->GetMethodByIndex(i);
std::vector<std::string> metadata = std::vector<std::string> metadata =
scriptBuilder.GetMetadataForTypeMethod(type->GetTypeId(), scriptBuilder.GetMetadataForTypeMethod(type->GetTypeId(),
func); func);
bool containsServiceAPI = false; bool containsServiceAPI = false;
for (std::string &str : metadata) { for (std::string& str : metadata) {
if (str != "ServiceAPI") if (str != "ServiceAPI")
continue; continue;
containsServiceAPI = true; containsServiceAPI = true;
@ -136,7 +136,7 @@ namespace Deer {
DEER_CORE_INFO("Registering function from object {0}.{1}", DEER_CORE_INFO("Registering function from object {0}.{1}",
type->GetName(), func->GetName()); type->GetName(), func->GetName());
asITypeInfo *retType = asITypeInfo* retType =
EditorEngine::scriptEngine->GetTypeInfoById( EditorEngine::scriptEngine->GetTypeInfoById(
func->GetReturnTypeId()); func->GetReturnTypeId());
@ -156,10 +156,10 @@ namespace Deer {
ext_dec << ", "; ext_dec << ", ";
int typeId; int typeId;
const char *name; const char* name;
func->GetParam(i, &typeId, nullptr, &name); func->GetParam(i, &typeId, nullptr, &name);
asITypeInfo *paramType = asITypeInfo* paramType =
scriptEngine->GetTypeInfoById(typeId); scriptEngine->GetTypeInfoById(typeId);
ext_dec << paramType->GetName(); ext_dec << paramType->GetName();
@ -171,9 +171,16 @@ namespace Deer {
DEER_CORE_INFO(ext_dec.str().c_str()); DEER_CORE_INFO(ext_dec.str().c_str());
ServiceScriptFunction* serviceScriptFunction =
new ServiceScriptFunction();
serviceScriptFunction->apiFunction = func;
serviceScriptFunction->scriptContext = scriptContext;
serviceScriptFunction->scriptObject = object;
AS_CHECK(scriptEngine->RegisterGlobalFunction( AS_CHECK(scriptEngine->RegisterGlobalFunction(
ext_dec.str().c_str(), asFUNCTION(apiFunction), ext_dec.str().c_str(), asFUNCTION(apiFunction),
asCALL_GENERIC)); asCALL_GENERIC, serviceScriptFunction));
} }
} }
} // namespace EditorEngine } // namespace EditorEngine

View File

@ -1,44 +1,42 @@
#include "DeerStudio/DeerStudio.h" #include "DeerStudio/DeerStudio.h"
#include "DeerStudio/EditorEngine.h" #include "DeerStudio/EditorEngine.h"
#include "DeerStudio/EditorEngine/DockPanel/DockPanelObject.h"
#include "DeerStudio/EditorEngine/DockPanel/DockPanelContext.h" #include "DeerStudio/EditorEngine/DockPanel/DockPanelContext.h"
#include "DeerStudio/EditorEngine/DockPanel/DockPanelObject.h"
#include "imgui.h" #include "imgui.h"
namespace Deer { namespace Deer {
namespace DeerStudio { namespace DeerStudio {
void panelEnable(EditorEngine::DockPanelObject& dpo); void panelEnable(EditorEngine::DockPanelObject& dpo);
void onPannelMenuBar() {
if (ImGui::BeginMenu("Dock Panels Show/Hide")) {
for (EditorEngine::DockPanelContext& pc : EditorEngine::dockPanelModules) {
if (pc.dockPanels.size() == 0)
continue;
if (pc.dockPanels.size() == 1){
panelEnable(pc.dockPanels[0]);
continue;
}
const char* name = pc.getName();
if (ImGui::BeginMenu(name)) {
for (EditorEngine::DockPanelObject& panel : pc.dockPanels) {
panelEnable(panel);
}
ImGui::EndMenu();
}
}
ImGui::EndMenu();
}
}
void panelEnable(EditorEngine::DockPanelObject& dpo) { void onPannelMenuBar() {
const char* name = dpo.getName(); for (EditorEngine::DockPanelContext& pc :
EditorEngine::dockPanelModules) {
bool enabled = dpo.getFlag(DockPannelFlag_ShowPannel); if (pc.dockPanels.size() == 0)
if (ImGui::MenuItem(name, nullptr, enabled)) { continue;
dpo.setFlag(DockPannelFlag_ShowPannel, !enabled);
} if (pc.dockPanels.size() == 1) {
} panelEnable(pc.dockPanels[0]);
} continue;
} }
const char* name = pc.getName();
if (ImGui::BeginMenu(name)) {
for (EditorEngine::DockPanelObject& panel : pc.dockPanels) {
panelEnable(panel);
}
ImGui::EndMenu();
}
}
}
void panelEnable(EditorEngine::DockPanelObject& dpo) {
const char* name = dpo.getName();
bool enabled = dpo.getFlag(DockPannelFlag_ShowPannel);
if (ImGui::MenuItem(name, nullptr, enabled)) {
dpo.setFlag(DockPannelFlag_ShowPannel, !enabled);
}
}
} // namespace DeerStudio
} // namespace Deer

View File

@ -1,11 +1,10 @@
void addComponentPopup(any@ data) { void addComponentPopup(any@ data) {
Entity entity; Entity entity;
data.retrieve(entity); data.retrieve(entity);
UI::titleCenter("Component"); UI::titleCenter("Component");
UI::separator(); UI::separator();
UI::menuSpace("Rendering", any(entity), addComponentRendering ); UI::menuSpace("Rendering", any(entity), addComponentRendering);
if (UI::menuItem("Script Component")) { if (UI::menuItem("Script Component")) {
} }
} }
@ -37,4 +36,4 @@ void addComponentRendering(any@ data) {
entity.createCameraComponent(); entity.createCameraComponent();
} }
} }
} }

View File

@ -7,10 +7,10 @@ void renderCameraComponent(any@ data) {
CameraComponent cameraComponent = entity.getCameraComponent(); CameraComponent cameraComponent = entity.getCameraComponent();
float fov = cameraComponent.fov; float fov = cameraComponent.fov;
float aspect = cameraComponent.aspectRatio; float aspect = cameraComponent.aspectRatio;
float nearZ = cameraComponent.nearZ; float nearZ = cameraComponent.nearZ;
float farZ = cameraComponent.farZ; float farZ = cameraComponent.farZ;
fov = UI::magicSlider("Fov", fov, 0.1); fov = UI::magicSlider("Fov", fov, 0.1);
if (fov > 180) if (fov > 180)
@ -31,10 +31,10 @@ void renderCameraComponent(any@ data) {
if (nearZ > farZ) if (nearZ > farZ)
farZ = nearZ; farZ = nearZ;
cameraComponent.fov = fov; cameraComponent.fov = fov;
cameraComponent.aspectRatio = aspect; cameraComponent.aspectRatio = aspect;
cameraComponent.nearZ = nearZ; cameraComponent.nearZ = nearZ;
cameraComponent.farZ = farZ; cameraComponent.farZ = farZ;
} }
void removeCameraComponent(any@ entity) { void removeCameraComponent(any@ entity) {
@ -44,4 +44,4 @@ void removeCameraComponent(any@ entity) {
if (UI::menuItem("Remove")) { if (UI::menuItem("Remove")) {
ent.removeCameraComponent(); ent.removeCameraComponent();
} }
} }

View File

@ -1,4 +1,3 @@
void renderMeshComponent(any@ data) { void renderMeshComponent(any@ data) {
Entity entity; Entity entity;
data.retrieve(entity); data.retrieve(entity);
@ -42,8 +41,7 @@ void renderMeshComponent(any@ data) {
} }
} }
void setMeshComponentMesh(any@ meshComponent_data, any@ mesh_data) {
void setMeshComponentMesh(any@ meshComponent_data, any@ mesh_data){
string mesh; string mesh;
mesh_data.retrieve(mesh); mesh_data.retrieve(mesh);
@ -60,4 +58,4 @@ void removeMeshComponent(any@ entity) {
if (UI::menuItem("Remove")) { if (UI::menuItem("Remove")) {
ent.removeMeshComponent(); ent.removeMeshComponent();
} }
} }

View File

@ -1,11 +1,10 @@
class PropertiesPannel : DockPanel { class PropertiesPannel : DockPanel {
float slider = 0; float slider = 0;
vec3 slid; vec3 slid;
vec3 slid2; vec3 slid2;
void onRender() { void onRender() {
Entity entity = activeEntity; Entity entity = Chewico::ActiveEntity::ActiveEntity::getActiveEntity();
// We don't want to change root options // We don't want to change root options
if (entity.isRoot) if (entity.isRoot)
@ -19,7 +18,6 @@ class PropertiesPannel : DockPanel {
UI::separator(); UI::separator();
UI::textColor(0.5, 0.5, 0.5f, "Id : " + entity.id); UI::textColor(0.5, 0.5, 0.5f, "Id : " + entity.id);
UI::sameline(); UI::sameline();
if (UI::buttonEnd("Add Component")) { if (UI::buttonEnd("Add Component")) {
UI::openPopup("ADD_COMPONENT", any(entity)); UI::openPopup("ADD_COMPONENT", any(entity));
@ -40,8 +38,7 @@ class PropertiesPannel : DockPanel {
if (entity.hasCameraComponent()) { if (entity.hasCameraComponent()) {
UI::componentNode_contextMenu("Camera Component", any(entity), renderCameraComponent, removeCameraComponent); UI::componentNode_contextMenu("Camera Component", any(entity), renderCameraComponent, removeCameraComponent);
} }
UI::space(); UI::space();
UI::separator(); UI::separator();
@ -65,4 +62,4 @@ class PropertiesPannel : DockPanel {
} }
} }
} }

View File

@ -1,4 +1,3 @@
void setShaderComponent(any@ shaderComponent_data, any@ shader_data) { void setShaderComponent(any@ shaderComponent_data, any@ shader_data) {
string shader; string shader;
shader_data.retrieve(shader); shader_data.retrieve(shader);

View File

@ -21,7 +21,7 @@ class TreePannel : DockPanel {
for (int i = 0; i < entity.childs.count; i++) { for (int i = 0; i < entity.childs.count; i++) {
Entity child = entity.childs[i]; Entity child = entity.childs[i];
bool isActive = child == activeEntity; bool isActive = child == Chewico::ActiveEntity::ActiveEntity::getActiveEntity();
string displayName = child.name; string displayName = child.name;
if (displayName == "") { if (displayName == "") {
@ -52,7 +52,7 @@ class TreePannel : DockPanel {
// We can't select the entity // We can't select the entity
if (UI::isItemClicked(0)) { if (UI::isItemClicked(0)) {
activeEntity = entity; Chewico::ActiveEntity::ActiveEntity::setActiveEntity(entity);
} }
} }

View File

@ -1,2 +0,0 @@
Entity activeEntity = Engine::getRoot();

View File

@ -1,4 +1,3 @@
void renameEntity(any@ data) { void renameEntity(any@ data) {
Entity entity; Entity entity;
data.retrieve(entity); data.retrieve(entity);
@ -11,4 +10,4 @@ void renameEntity(any@ data) {
if (UI::button("Accept")) { if (UI::button("Accept")) {
UI::closePopup(); UI::closePopup();
} }
} }

View File

@ -1,6 +1,8 @@
class Test : DockPanel { class Test : DockPanel {
void onRender() { void onRender() {
Entity ent = Chewico::ActiveEntity::ActiveEntity::getActiveEntity();
UI::text("Hi"); UI::text("Hi");
Chewico::ActiveEntity::ActiveEntity::getActiveEntity(); UI::text(ent.name);
} }
} }

View File

@ -14,4 +14,4 @@ class ActiveEntity : ServiceScript {
void setActiveEntity(Entity ent) { void setActiveEntity(Entity ent) {
entity = ent; entity = ent;
} }
} }