From 4398caea07d109fae492e24c975a0d18d4b8e2ed Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Wed, 26 Jul 2023 04:28:41 +0200 Subject: [PATCH] :angel: Script: raw OGRE Overlay bindings (demo) New script API: * `class Ogre::OverlayManager` * `class Ogre::Overlay` * `class Ogre::OverlayElement` * `enum Ogre::GuiMetricsMode` * `enum Ogre::GuiHorizontalAlignment` New example script: example_ogre_overlays.as - a test script I used while developing, creates 1 "Panel" overlay with material "tracks/wheelface" and some GUI controls. --- resources/scripts/example_ogre_overlays.as | 77 ++++++++++++++++++ .../scripting/bindings/OgreAngelscript.cpp | 81 +++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 resources/scripts/example_ogre_overlays.as diff --git a/resources/scripts/example_ogre_overlays.as b/resources/scripts/example_ogre_overlays.as new file mode 100644 index 0000000000..c7a2486df2 --- /dev/null +++ b/resources/scripts/example_ogre_overlays.as @@ -0,0 +1,77 @@ +// TEST SCRIPT for Ogre Overlays +// builtin element types are listed in RoR.log on startup: +// * Panel registered. +// * BorderPanel registered. +// * TextArea registered. +// =================================================== +// #### WARNING - DANGEROUS API #### +// OGRE objects don't use reference counting +// - do not keep pointers longer than absolutely necessary! +// Prefer always looking up the resource from OGRE - slower but safer. +// =================================================== + +bool ov_fail = false; + +bool pa_fail = false; +int framecounter = 0; +float pos_step = 50; // pixels + +void frameStep(float dt) +{ + Ogre::Overlay@ ov; + if (!ov_fail) { + // NOTE: getByName() will calmly return NULL if overlay doesn't exist. + @ov = Ogre::OverlayManager::getSingleton().getByName("ov"); + // CAUTION: attempt to create the same overlay again will throw an exception, interrupting the script in between! + if (@ov == null) { @ov = Ogre::OverlayManager::getSingleton().create("ov"); } + if (@ov == null) { ov_fail = true; } + else { ov.show(); } + } + + Ogre::OverlayElement@ pa; + + if (!pa_fail ){ + if ( Ogre::OverlayManager::getSingleton().hasOverlayElement("pa")) { + + // CAUTION: getOverlayElement() will throw exception if not found, always do `hasOverlayElement()` first! + @pa = Ogre::OverlayManager::getSingleton().getOverlayElement("pa"); + } + // CAUTION: using the same name twice will throw an exception, interrupting the script in between! + if (@pa == null ) { @pa = Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "pa"); + if (@pa == null ) { pa_fail=true; } + else { +// game.log("adding pa to ov"); + ov.add2D(pa); + pa.setMetricsMode(Ogre::GMM_PIXELS); + pa.setPosition(100,100); + pa.setDimensions(100,100); + pa.show(); + } + } + pa.setMaterialName("tracks/wheelface", 'OgreAutodetect'); + } + + ImGui::Text("overlays should work; ov_fail:"+ov_fail+", pa_fail:"+pa_fail + +", frames:"+framecounter); + framecounter++; + if (!pa_fail && @pa != null) + { + + ImGui::TextDisabled("The wheel overlay:"); + if (ImGui::Button("Hide")) { pa.hide(); } + ImGui::SameLine(); if (ImGui::Button("Show")) { pa.show(); } + + if (ImGui::Button("Position: Left+")) { pa.setLeft(pa.getLeft()+pos_step); } + ImGui::SameLine(); if (ImGui::Button("Position:left-")) { pa.setLeft(pa.getLeft()-pos_step); } + + if (ImGui::Button("Position: Top+")) { pa.setTop(pa.getTop()+pos_step); } + ImGui::SameLine(); if (ImGui::Button("Position:Top-")) { pa.setTop(pa.getTop()-pos_step); } + + if (ImGui::Button("Width+")) { pa.setWidth(pa.getWidth()+pos_step); } + ImGui::SameLine(); if (ImGui::Button("Width-")) { pa.setWidth(pa.getWidth()-pos_step); } + + if (ImGui::Button("height+")) { pa.setHeight(pa.getHeight()+pos_step); } + ImGui::SameLine(); if (ImGui::Button("height-")) { pa.setHeight(pa.getHeight()-pos_step); } + + } +} diff --git a/source/main/scripting/bindings/OgreAngelscript.cpp b/source/main/scripting/bindings/OgreAngelscript.cpp index 1bf4da447b..20b984543e 100644 --- a/source/main/scripting/bindings/OgreAngelscript.cpp +++ b/source/main/scripting/bindings/OgreAngelscript.cpp @@ -26,6 +26,11 @@ #include "Application.h" #include "ScriptEngine.h" +#include +#include +#include +#include + using namespace Ogre; using namespace AngelScript; @@ -223,6 +228,7 @@ void registerOgreRadian(AngelScript::asIScriptEngine* engine); void registerOgreDegree(AngelScript::asIScriptEngine* engine); void registerOgreQuaternion(AngelScript::asIScriptEngine* engine); void registerOgreTexture(AngelScript::asIScriptEngine* engine); +void registerOgreOverlay(AngelScript::asIScriptEngine* engine); void registerOgreColourValue(AngelScript::asIScriptEngine* engine); // main registration method @@ -263,6 +269,7 @@ void RoR::RegisterOgreObjects(AngelScript::asIScriptEngine* engine) registerOgreQuaternion(engine); registerOgreTexture(engine); registerOgreColourValue(engine); + registerOgreOverlay(engine); } // register Ogre::Vector3 @@ -812,3 +819,77 @@ void registerOgreTexture(AngelScript::asIScriptEngine* engine) engine->SetDefaultNamespace(""); } + +void registerOgreOverlay(AngelScript::asIScriptEngine* engine) +{ + engine->SetDefaultNamespace("Ogre"); + + // Register the GuiMetricsMode enum + engine->RegisterEnum("GuiMetricsMode"); + engine->RegisterEnumValue("GuiMetricsMode", "GMM_PIXELS", Ogre::GMM_PIXELS); + engine->RegisterEnumValue("GuiMetricsMode", "GMM_RELATIVE", Ogre::GMM_RELATIVE); + engine->RegisterEnumValue("GuiMetricsMode", "GMM_RELATIVE_ASPECT_ADJUSTED", Ogre::GMM_RELATIVE_ASPECT_ADJUSTED); + + // Register the GuiHorizontalAlignment enum + engine->RegisterEnum("GuiHorizontalAlignment"); + engine->RegisterEnumValue("GuiHorizontalAlignment", "GHA_LEFT", Ogre::GHA_LEFT); + engine->RegisterEnumValue("GuiHorizontalAlignment", "GHA_CENTER", Ogre::GHA_CENTER); + engine->RegisterEnumValue("GuiHorizontalAlignment", "GHA_RIGHT", Ogre::GHA_RIGHT); + + + // Register the OverlayElement class + engine->RegisterObjectType("OverlayElement", 0, asOBJ_REF | asOBJ_NOCOUNT); + engine->RegisterObjectMethod("OverlayElement", "void setPosition(float, float)", asMETHODPR(Ogre::OverlayElement, setPosition, (float, float), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setDimensions(float, float)", asMETHODPR(Ogre::OverlayElement, setDimensions, (float, float), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setMaterialName(const string&in, const string&in)", asMETHOD(Ogre::OverlayElement, setMaterialName), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "string getName() const", asMETHOD(Ogre::OverlayElement, getName), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "float getLeft() const", asMETHOD(Ogre::OverlayElement, getLeft), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "float getTop() const", asMETHOD(Ogre::OverlayElement, getTop), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "float getWidth() const", asMETHODPR(Ogre::OverlayElement, getWidth, () const, float), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "float getHeight() const", asMETHODPR(Ogre::OverlayElement, getHeight, () const, float), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "string getMaterialName() const", asMETHOD(Ogre::OverlayElement, getMaterialName), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "string getParameter(const string&in) const", asMETHODPR(Ogre::OverlayElement, getParameter, (const std::string&) const, std::string), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void show()", asMETHOD(Ogre::OverlayElement, show), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void hide()", asMETHOD(Ogre::OverlayElement, hide), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setCaption(const string&in)", asMETHOD(Ogre::OverlayElement, setCaption), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setColour(float, float, float, float)", asMETHOD(Ogre::OverlayElement, setColour), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setLeft(float)", asMETHODPR(Ogre::OverlayElement, setLeft, (float), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setTop(float)", asMETHODPR(Ogre::OverlayElement, setTop, (float), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setWidth(float)", asMETHOD(Ogre::OverlayElement, setWidth), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setHeight(float)", asMETHOD(Ogre::OverlayElement, setHeight), asCALL_THISCALL); + // Register the getters and setters for GuiMetricsMode + engine->RegisterObjectMethod("OverlayElement", "GuiMetricsMode getMetricsMode() const", asMETHODPR(Ogre::OverlayElement, getMetricsMode, () const, Ogre::GuiMetricsMode), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setMetricsMode(GuiMetricsMode)", asMETHODPR(Ogre::OverlayElement, setMetricsMode, (Ogre::GuiMetricsMode), void), asCALL_THISCALL); + // Register the getters and setters for GuiHorizontalAlignment + engine->RegisterObjectMethod("OverlayElement", "GuiHorizontalAlignment getHorizontalAlignment() const", asMETHODPR(Ogre::OverlayElement, getHorizontalAlignment, () const, Ogre::GuiHorizontalAlignment), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayElement", "void setHorizontalAlignment(GuiHorizontalAlignment)", asMETHODPR(Ogre::OverlayElement, setHorizontalAlignment, (Ogre::GuiHorizontalAlignment), void), asCALL_THISCALL); + + + // Register the Overlay class + engine->RegisterObjectType("Overlay", 0, asOBJ_REF | asOBJ_NOCOUNT); + engine->RegisterObjectMethod("Overlay", "void show()", asMETHODPR(Ogre::Overlay, show, (), void), asCALL_THISCALL); + engine->RegisterObjectMethod("Overlay", "void hide()", asMETHODPR(Ogre::Overlay, hide, (), void), asCALL_THISCALL); + engine->RegisterObjectMethod("Overlay", "void add2D(OverlayElement@)", asMETHOD(Ogre::Overlay, add2D), asCALL_THISCALL); + //engine->RegisterObjectMethod("Overlay", "void add3D(OverlayContainer@)", asMETHOD(Ogre::Overlay, add3D), asCALL_THISCALL); + engine->RegisterObjectMethod("Overlay", "void remove2D(OverlayElement@)", asMETHOD(Ogre::Overlay, remove2D), asCALL_THISCALL); + //engine->RegisterObjectMethod("Overlay", "void remove3D(OverlayContainer@)", asMETHOD(Ogre::Overlay, remove3D), asCALL_THISCALL); + engine->RegisterObjectMethod("Overlay", "bool isVisible() const", asMETHODPR(Ogre::Overlay, isVisible, () const, bool), asCALL_THISCALL); + engine->RegisterObjectMethod("Overlay", "void setZOrder(int)", asMETHOD(Ogre::Overlay, setZOrder), asCALL_THISCALL); + + + // Register the OverlayManager class + engine->RegisterObjectType("OverlayManager", 0, asOBJ_REF | asOBJ_NOCOUNT); + engine->RegisterObjectMethod("OverlayManager", "OverlayElement@ createOverlayElement(const string&in, const string&in)", asMETHOD(Ogre::OverlayManager, createOverlayElement), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "Overlay@ create(const string&in)", asMETHOD(Ogre::OverlayManager, create), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "void destroy(const string&in)", asMETHODPR(Ogre::OverlayManager, destroy, (const Ogre::String&), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "Overlay@ getByName(const string&in) const", asMETHOD(Ogre::OverlayManager, getByName), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "void destroyAll()", asMETHODPR(Ogre::OverlayManager, destroyAll, (), void), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "bool hasOverlayElement(const string&in) const", asMETHOD(Ogre::OverlayManager, hasOverlayElement), asCALL_THISCALL); + engine->RegisterObjectMethod("OverlayManager", "OverlayElement@ getOverlayElement(const string&in) const", asMETHOD(Ogre::OverlayManager, getOverlayElement), asCALL_THISCALL); + + engine->SetDefaultNamespace("Ogre::OverlayManager"); + engine->RegisterGlobalFunction("OverlayManager& getSingleton()", asFUNCTION(OverlayManager::getSingleton), asCALL_CDECL); + + engine->SetDefaultNamespace(""); + +}