From e3461e90531345650fe70ada38d875a68f87f416 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 4 Jul 2023 19:27:16 +1000 Subject: [PATCH] Start of Interface callbacks, starting with a bindCanvas function for the whole screen --- source/client/StarClientApplication.cpp | 5 + source/frontend/CMakeLists.txt | 2 + source/frontend/StarInterfaceLuaBindings.cpp | 21 +++ source/frontend/StarInterfaceLuaBindings.hpp | 16 +++ source/frontend/StarMainInterface.cpp | 23 ++++ source/frontend/StarMainInterface.hpp | 5 + source/frontend/StarScriptPane.cpp | 1 + source/frontend/StarWidgetLuaBindings.cpp | 129 ++++++++++--------- source/frontend/StarWidgetLuaBindings.hpp | 9 ++ source/game/StarUniverseClient.cpp | 8 ++ source/game/StarUniverseClient.hpp | 4 + source/game/StarWorldClient.cpp | 11 +- source/game/StarWorldClient.hpp | 3 + source/game/scripting/StarLuaRoot.cpp | 76 +++++++---- source/game/scripting/StarLuaRoot.hpp | 8 +- source/windowing/StarCanvasWidget.cpp | 68 +++++++--- source/windowing/StarCanvasWidget.hpp | 2 + 17 files changed, 283 insertions(+), 108 deletions(-) create mode 100644 source/frontend/StarInterfaceLuaBindings.cpp create mode 100644 source/frontend/StarInterfaceLuaBindings.hpp diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp index 0abd97d..cb5b2de 100644 --- a/source/client/StarClientApplication.cpp +++ b/source/client/StarClientApplication.cpp @@ -15,6 +15,8 @@ #include "StarWorldClient.hpp" #include "StarRootLoader.hpp" +#include "StarInterfaceLuaBindings.hpp" + namespace Star { Json const AdditionalAssetsSettings = Json::parseJson(R"JSON( @@ -384,6 +386,7 @@ void ClientApplication::render() { } else if (m_state > MainAppState::Title) { WorldClientPtr worldClient = m_universeClient->worldClient(); + RendererPtr renderer = Application::renderer(); if (worldClient) { auto totalStart = Time::monotonicMicroseconds(); @@ -480,6 +483,7 @@ void ClientApplication::changeState(MainAppState newState) { m_playerStorage = make_shared(m_root->toStoragePath("player")); m_statistics = make_shared(m_root->toStoragePath("player"), appController()->statisticsService()); m_universeClient = make_shared(m_playerStorage, m_statistics); + m_mainMixer->setUniverseClient(m_universeClient); m_titleScreen = make_shared(m_playerStorage, m_mainMixer->mixer()); if (auto renderer = Application::renderer()) @@ -596,6 +600,7 @@ void ClientApplication::changeState(MainAppState newState) { m_worldPainter = make_shared(); m_mainInterface = make_shared(m_universeClient, m_worldPainter, m_cinematicOverlay); + m_universeClient->setLuaCallbacks("interface", LuaBindings::makeInterfaceCallbacks(m_mainInterface.get())); m_mainMixer->setWorldPainter(m_worldPainter); if (auto renderer = Application::renderer()) { diff --git a/source/frontend/CMakeLists.txt b/source/frontend/CMakeLists.txt index 50c4229..4772aa0 100644 --- a/source/frontend/CMakeLists.txt +++ b/source/frontend/CMakeLists.txt @@ -32,6 +32,7 @@ SET (star_frontend_HEADERS StarGraphicsMenu.hpp StarInventory.hpp StarInterfaceCursor.hpp + StarInterfaceLuaBindings.hpp StarItemTooltip.hpp StarJoinRequestDialog.hpp StarKeybindingsMenu.hpp @@ -80,6 +81,7 @@ SET (star_frontend_SOURCES StarGraphicsMenu.cpp StarInventory.cpp StarInterfaceCursor.cpp + StarInterfaceLuaBindings.cpp StarItemTooltip.cpp StarJoinRequestDialog.cpp StarKeybindingsMenu.cpp diff --git a/source/frontend/StarInterfaceLuaBindings.cpp b/source/frontend/StarInterfaceLuaBindings.cpp new file mode 100644 index 0000000..a9257aa --- /dev/null +++ b/source/frontend/StarInterfaceLuaBindings.cpp @@ -0,0 +1,21 @@ +#include "StarInterfaceLuaBindings.hpp" +#include "StarWidgetLuaBindings.hpp" +#include "StarJsonExtra.hpp" +#include "StarLuaGameConverters.hpp" +#include "StarMainInterface.hpp" + +namespace Star { + +LuaCallbacks LuaBindings::makeInterfaceCallbacks(MainInterface* mainInterface) { + LuaCallbacks callbacks; + + callbacks.registerCallback("bindCanvas", [mainInterface](String const& canvasName) -> Maybe { + if (auto canvas = mainInterface->fetchCanvas(canvasName)) + return canvas; + return {}; + }); + + return callbacks; +} + +} diff --git a/source/frontend/StarInterfaceLuaBindings.hpp b/source/frontend/StarInterfaceLuaBindings.hpp new file mode 100644 index 0000000..8bc0f0a --- /dev/null +++ b/source/frontend/StarInterfaceLuaBindings.hpp @@ -0,0 +1,16 @@ +#ifndef STAR_INTERFACE_LUA_BINDINGS_HPP +#define STAR_INTERFACE_LUA_BINDINGS_HPP + +#include "StarLua.hpp" + +namespace Star { + +STAR_CLASS(MainInterface); + +namespace LuaBindings { + LuaCallbacks makeInterfaceCallbacks(MainInterface* mainInterface); +} + +} + +#endif diff --git a/source/frontend/StarMainInterface.cpp b/source/frontend/StarMainInterface.cpp index 0475663..592bc6e 100644 --- a/source/frontend/StarMainInterface.cpp +++ b/source/frontend/StarMainInterface.cpp @@ -24,6 +24,7 @@ #include "StarWireInterface.hpp" #include "StarTeamBar.hpp" #include "StarStatusPane.hpp" +#include "StarCanvasWidget.hpp" #include "StarLabelWidget.hpp" #include "StarItemSlotWidget.hpp" #include "StarPlayer.hpp" @@ -792,6 +793,12 @@ void MainInterface::update() { m_client->mainPlayer()->setBusyState(PlayerBusyState::Chatting); else m_client->mainPlayer()->setBusyState(PlayerBusyState::None); + + for (auto& pair : m_canvases) { + pair.second->setPosition(Vec2I()); + pair.second->setSize(Vec2I(m_guiContext->windowSize())); + pair.second->update(); + } } void MainInterface::renderInWorldElements() { @@ -820,6 +827,10 @@ void MainInterface::render() { renderMainBar(); renderDebug(); + RectI screenRect = RectI::withSize(Vec2I(), Vec2I(m_guiContext->windowSize())); + for (auto& pair : m_canvases) + pair.second->render(screenRect); + renderWindows(); renderCursor(); } @@ -912,6 +923,18 @@ void MainInterface::warpTo(WarpAction const& warpAction) { } } +CanvasWidgetPtr MainInterface::fetchCanvas(String const& canvasName) { + if (auto canvasPtr = m_canvases.ptr(canvasName)) + return *canvasPtr; + else { + CanvasWidgetPtr canvas = m_canvases.emplace(canvasName, make_shared()).first->second; + canvas->setPosition(Vec2I()); + canvas->setSize(Vec2I(m_guiContext->windowSize())); + canvas->setIgnoreInterfaceScale(true); + return canvas; + } +} + PanePtr MainInterface::createEscapeDialog() { auto assets = Root::singleton().assets(); diff --git a/source/frontend/StarMainInterface.hpp b/source/frontend/StarMainInterface.hpp index 403b250..3e05b9b 100644 --- a/source/frontend/StarMainInterface.hpp +++ b/source/frontend/StarMainInterface.hpp @@ -42,6 +42,7 @@ STAR_CLASS(QuestTrackerPane); STAR_CLASS(ContainerInteractor); STAR_CLASS(ScriptPane); STAR_CLASS(ChatBubbleManager); +STAR_CLASS(CanvasWidget); STAR_STRUCT(GuiMessage); STAR_CLASS(MainInterface); @@ -114,6 +115,8 @@ public: void warpToOwnShip(); void warpTo(WarpAction const& warpAction); + CanvasWidgetPtr fetchCanvas(String const& canvasName); + private: PanePtr createEscapeDialog(); @@ -167,6 +170,8 @@ private: ScriptPanePtr m_collections; Map m_interactionScriptPanes; + StringMap m_canvases; + ChatPtr m_chat; ClientCommandProcessorPtr m_clientCommandProcessor; RadioMessagePopupPtr m_radioMessagePopup; diff --git a/source/frontend/StarScriptPane.cpp b/source/frontend/StarScriptPane.cpp index 38659f1..b09211d 100644 --- a/source/frontend/StarScriptPane.cpp +++ b/source/frontend/StarScriptPane.cpp @@ -12,6 +12,7 @@ #include "StarPlayer.hpp" #include "StarUniverseClient.hpp" #include "StarWidgetLuaBindings.hpp" +#include "StarInterfaceLuaBindings.hpp" #include "StarCanvasWidget.hpp" #include "StarItemTooltip.hpp" #include "StarItemGridWidget.hpp" diff --git a/source/frontend/StarWidgetLuaBindings.cpp b/source/frontend/StarWidgetLuaBindings.cpp index eb3ff5b..fb84ff8 100644 --- a/source/frontend/StarWidgetLuaBindings.cpp +++ b/source/frontend/StarWidgetLuaBindings.cpp @@ -17,74 +17,77 @@ namespace Star { -template <> -struct LuaConverter : LuaUserDataConverter {}; +LuaMethods LuaUserDataMethods::make() { + LuaMethods methods; -template <> -struct LuaUserDataMethods { - static LuaMethods make() { - LuaMethods methods; + methods.registerMethodWithSignature("size", mem_fn(&CanvasWidget::size)); + methods.registerMethodWithSignature("mousePosition", mem_fn(&CanvasWidget::mousePosition)); - methods.registerMethodWithSignature("size", mem_fn(&CanvasWidget::size)); - methods.registerMethodWithSignature("mousePosition", mem_fn(&CanvasWidget::mousePosition)); + methods.registerMethodWithSignature("clear", mem_fn(&CanvasWidget::clear)); - methods.registerMethodWithSignature("clear", mem_fn(&CanvasWidget::clear)); + methods.registerMethod("drawDrawable", [](CanvasWidgetPtr canvasWidget, Drawable drawable) { + canvasWidget->drawDrawable(move(drawable), Vec2F()); + }); - methods.registerMethod("drawImage", - [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, Maybe scale, Maybe color, Maybe centered) { - if (centered && *centered) - canvasWidget->drawImageCentered(image, position, scale.value(1.0f), color.value(Color::White).toRgba()); - else - canvasWidget->drawImage(image, position, scale.value(1.0f), color.value(Color::White).toRgba()); - }); - methods.registerMethod("drawImageDrawable", - [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, MVariant scale, Maybe color, Maybe rotation) { - auto drawable = Drawable::makeImage(image, 1.0, true, {0.0, 0.0}, color.value(Color::White)); - if (auto s = scale.maybe()) - drawable.transform(Mat3F::scaling(*s)); - else if(auto s = scale.maybe()) - drawable.transform(Mat3F::scaling(*s)); - if (rotation) - drawable.rotate(*rotation); - canvasWidget->drawDrawable(drawable, position); - }); - methods.registerMethod("drawImageRect", - [](CanvasWidgetPtr canvasWidget, String image, RectF texCoords, RectF screenCoords, Maybe color) { - canvasWidget->drawImageRect(image, texCoords, screenCoords, color.value(Color::White).toRgba()); - }); - methods.registerMethod("drawTiledImage", - [](CanvasWidgetPtr canvasWidget, String image, Vec2D offset, RectF screenCoords, Maybe scale, Maybe color) { - canvasWidget->drawTiledImage(image, scale.value(1.0f), offset, screenCoords, color.value(Color::White).toRgba()); - }); - methods.registerMethod("drawLine", - [](CanvasWidgetPtr canvasWidget, Vec2F begin, Vec2F end, Maybe color, Maybe lineWidth) { - canvasWidget->drawLine(begin, end, color.value(Color::White).toRgba(), lineWidth.value(1.0f)); - }); - methods.registerMethod("drawRect", - [](CanvasWidgetPtr canvasWidget, RectF rect, Maybe color) { - canvasWidget->drawRect(rect, color.value(Color::White).toRgba()); - }); - methods.registerMethod("drawPoly", - [](CanvasWidgetPtr canvasWidget, PolyF poly, Maybe color, Maybe lineWidth) { - canvasWidget->drawPoly(poly, color.value(Color::White).toRgba(), lineWidth.value(1.0f)); - }); - methods.registerMethod("drawTriangles", - [](CanvasWidgetPtr canvasWidget, List triangles, Maybe color) { - auto tris = triangles.transformed([](PolyF const& poly) { - if (poly.sides() != 3) - throw StarException("Triangle must have exactly 3 sides"); - return tuple(poly.vertex(0), poly.vertex(1), poly.vertex(2)); - }); - canvasWidget->drawTriangles(tris, color.value(Color::White).toRgba()); - }); - methods.registerMethod("drawText", - [](CanvasWidgetPtr canvasWidget, String text, Json tp, unsigned fontSize, Maybe color, Maybe lineSpacing, Maybe font, Maybe directives) { - canvasWidget->drawText(text, TextPositioning(tp), fontSize, color.value(Color::White).toRgba(), FontMode::Normal, lineSpacing.value(DefaultLineSpacing), font.value(""), directives.value("")); - }); + methods.registerMethod("drawDrawables", [](CanvasWidgetPtr canvasWidget, List drawables) { + for (auto& drawable : drawables) + canvasWidget->drawDrawable(move(drawable), Vec2F()); + }); - return methods; - } -}; + methods.registerMethod("drawImage", + [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, Maybe scale, Maybe color, Maybe centered) { + if (centered && *centered) + canvasWidget->drawImageCentered(image, position, scale.value(1.0f), color.value(Color::White).toRgba()); + else + canvasWidget->drawImage(image, position, scale.value(1.0f), color.value(Color::White).toRgba()); + }); + methods.registerMethod("drawImageDrawable", + [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, MVariant scale, Maybe color, Maybe rotation) { + auto drawable = Drawable::makeImage(image, 1.0, true, {0.0, 0.0}, color.value(Color::White)); + if (auto s = scale.maybe()) + drawable.transform(Mat3F::scaling(*s)); + else if(auto s = scale.maybe()) + drawable.transform(Mat3F::scaling(*s)); + if (rotation) + drawable.rotate(*rotation); + canvasWidget->drawDrawable(drawable, position); + }); + methods.registerMethod("drawImageRect", + [](CanvasWidgetPtr canvasWidget, String image, RectF texCoords, RectF screenCoords, Maybe color) { + canvasWidget->drawImageRect(image, texCoords, screenCoords, color.value(Color::White).toRgba()); + }); + methods.registerMethod("drawTiledImage", + [](CanvasWidgetPtr canvasWidget, String image, Vec2D offset, RectF screenCoords, Maybe scale, Maybe color) { + canvasWidget->drawTiledImage(image, scale.value(1.0f), offset, screenCoords, color.value(Color::White).toRgba()); + }); + methods.registerMethod("drawLine", + [](CanvasWidgetPtr canvasWidget, Vec2F begin, Vec2F end, Maybe color, Maybe lineWidth) { + canvasWidget->drawLine(begin, end, color.value(Color::White).toRgba(), lineWidth.value(1.0f)); + }); + methods.registerMethod("drawRect", + [](CanvasWidgetPtr canvasWidget, RectF rect, Maybe color) { + canvasWidget->drawRect(rect, color.value(Color::White).toRgba()); + }); + methods.registerMethod("drawPoly", + [](CanvasWidgetPtr canvasWidget, PolyF poly, Maybe color, Maybe lineWidth) { + canvasWidget->drawPoly(poly, color.value(Color::White).toRgba(), lineWidth.value(1.0f)); + }); + methods.registerMethod("drawTriangles", + [](CanvasWidgetPtr canvasWidget, List triangles, Maybe color) { + auto tris = triangles.transformed([](PolyF const& poly) { + if (poly.sides() != 3) + throw StarException("Triangle must have exactly 3 sides"); + return tuple(poly.vertex(0), poly.vertex(1), poly.vertex(2)); + }); + canvasWidget->drawTriangles(tris, color.value(Color::White).toRgba()); + }); + methods.registerMethod("drawText", + [](CanvasWidgetPtr canvasWidget, String text, Json tp, unsigned fontSize, Maybe color, Maybe lineSpacing, Maybe font, Maybe directives) { + canvasWidget->drawText(text, TextPositioning(tp), fontSize, color.value(Color::White).toRgba(), FontMode::Normal, lineSpacing.value(DefaultLineSpacing), font.value(""), directives.value("")); + }); + + return methods; +} LuaCallbacks LuaBindings::makeWidgetCallbacks(Widget* parentWidget, GuiReader* reader) { LuaCallbacks callbacks; diff --git a/source/frontend/StarWidgetLuaBindings.hpp b/source/frontend/StarWidgetLuaBindings.hpp index fee5a96..48d6ab2 100644 --- a/source/frontend/StarWidgetLuaBindings.hpp +++ b/source/frontend/StarWidgetLuaBindings.hpp @@ -7,6 +7,15 @@ namespace Star { STAR_CLASS(Widget); +STAR_CLASS(CanvasWidget); + +template <> +struct LuaConverter : LuaUserDataConverter {}; + +template <> +struct LuaUserDataMethods { + static LuaMethods make(); +}; namespace LuaBindings { LuaCallbacks makeWidgetCallbacks(Widget* parentWidget, GuiReader* reader); diff --git a/source/game/StarUniverseClient.cpp b/source/game/StarUniverseClient.cpp index 783c5d3..1622518 100644 --- a/source/game/StarUniverseClient.cpp +++ b/source/game/StarUniverseClient.cpp @@ -112,6 +112,8 @@ Maybe UniverseClient::connect(UniverseConnection connection, bool allowA m_mainPlayer->setClientContext(m_clientContext); m_mainPlayer->setStatistics(m_statistics); m_worldClient = make_shared(m_mainPlayer); + for (auto& pair : m_luaCallbacks) + m_worldClient->setLuaCallbacks(pair.first, pair.second); m_connection = move(connection); m_celestialDatabase = make_shared(move(success->celestialInformation)); @@ -436,6 +438,12 @@ uint16_t UniverseClient::maxPlayers() { return m_serverInfo.apply([](auto const& info) { return info.maxPlayers; }).value(1); } +void UniverseClient::setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks) { + m_luaCallbacks[groupName] = callbacks; + if (m_worldClient) + m_worldClient->setLuaCallbacks(groupName, callbacks); +} + ClockConstPtr UniverseClient::universeClock() const { return m_universeClock; } diff --git a/source/game/StarUniverseClient.hpp b/source/game/StarUniverseClient.hpp index c5213cf..b26f2df 100644 --- a/source/game/StarUniverseClient.hpp +++ b/source/game/StarUniverseClient.hpp @@ -85,6 +85,8 @@ public: uint16_t players(); uint16_t maxPlayers(); + void setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks); + ClockConstPtr universeClock() const; CelestialLogConstPtr celestialLog() const; JsonRpcInterfacePtr rpcInterface() const; @@ -117,6 +119,8 @@ private: SystemWorldClientPtr m_systemWorldClient; Maybe m_connection; Maybe m_serverInfo; + + StringMap m_luaCallbacks; CelestialSlaveDatabasePtr m_celestialDatabase; ClientContextPtr m_clientContext; diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index 552b6e2..f25c45b 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -45,6 +45,8 @@ WorldClient::WorldClient(PlayerPtr mainPlayer) { m_collisionDebug = false; m_inWorld = false; + m_luaRoot = make_shared(); + m_mainPlayer = mainPlayer; centerClientWindowOnPlayer(Vec2U(100, 100)); @@ -895,6 +897,10 @@ List WorldClient::getOutgoingPackets() { return std::move(m_outgoingPackets); } +void WorldClient::setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks) { + m_luaRoot->addCallbacks(groupName, callbacks); +} + void WorldClient::update() { if (!inWorld()) return; @@ -1486,7 +1492,7 @@ void WorldClient::initWorld(WorldStartPacket const& startPacket) { m_entityMap = make_shared(m_worldTemplate->size(), entitySpace.first, entitySpace.second); m_tileArray = make_shared(m_worldTemplate->size()); m_damageManager = make_shared(this, startPacket.clientId); - m_luaRoot = make_shared(); + m_luaRoot->restart(); m_luaRoot->tuneAutoGarbageCollection(m_clientConfig.getFloat("luaGcPause"), m_clientConfig.getFloat("luaGcStepMultiplier")); m_playerStart = startPacket.playerRespawn; m_respawnInWorld = startPacket.respawnInWorld; @@ -1559,7 +1565,8 @@ void WorldClient::clearWorld() { m_tileArray.reset(); m_damageManager.reset(); - m_luaRoot.reset(); + + m_luaRoot->shutdown(); m_particles.reset(); diff --git a/source/game/StarWorldClient.hpp b/source/game/StarWorldClient.hpp index 9c00130..b8e9504 100644 --- a/source/game/StarWorldClient.hpp +++ b/source/game/StarWorldClient.hpp @@ -127,6 +127,9 @@ public: void handleIncomingPackets(List const& packets); List getOutgoingPackets(); + + // Sets default callbacks in the LuaRoot. + void setLuaCallbacks(String const& groupName, LuaCallbacks const& callbacks); // Set the rendering window for this client. void setClientWindow(RectI window); diff --git a/source/game/scripting/StarLuaRoot.cpp b/source/game/scripting/StarLuaRoot.cpp index 4d6e8cf..d41e8fc 100644 --- a/source/game/scripting/StarLuaRoot.cpp +++ b/source/game/scripting/StarLuaRoot.cpp @@ -5,16 +5,10 @@ namespace Star { LuaRoot::LuaRoot() { auto& root = Root::singleton(); - - m_luaEngine = LuaEngine::create(root.configuration()->get("safeScripts").toBool()); - - m_luaEngine->setRecursionLimit(root.configuration()->get("scriptRecursionLimit").toUInt()); - m_luaEngine->setInstructionLimit(root.configuration()->get("scriptInstructionLimit").toUInt()); - m_luaEngine->setProfilingEnabled(root.configuration()->get("scriptProfilingEnabled").toBool()); - m_luaEngine->setInstructionMeasureInterval(root.configuration()->get("scriptInstructionMeasureInterval").toUInt()); - m_scriptCache = make_shared(); + restart(); + m_rootReloadListener = make_shared([cache = m_scriptCache]() { cache->clear(); }); @@ -24,6 +18,40 @@ LuaRoot::LuaRoot() { } LuaRoot::~LuaRoot() { + shutdown(); +} + +void LuaRoot::loadScript(String const& assetPath) { + m_scriptCache->loadScript(*m_luaEngine, assetPath); +} + +bool LuaRoot::scriptLoaded(String const& assetPath) const { + return m_scriptCache->scriptLoaded(assetPath); +} + +void LuaRoot::unloadScript(String const& assetPath) { + m_scriptCache->unloadScript(assetPath); +} + +void LuaRoot::restart() { + shutdown(); + + auto& root = Root::singleton(); + + m_luaEngine = LuaEngine::create(root.configuration()->get("safeScripts").toBool()); + + m_luaEngine->setRecursionLimit(root.configuration()->get("scriptRecursionLimit").toUInt()); + m_luaEngine->setInstructionLimit(root.configuration()->get("scriptInstructionLimit").toUInt()); + m_luaEngine->setProfilingEnabled(root.configuration()->get("scriptProfilingEnabled").toBool()); + m_luaEngine->setInstructionMeasureInterval(root.configuration()->get("scriptInstructionMeasureInterval").toUInt()); +} + +void LuaRoot::shutdown() { + clearScriptCache(); + + if (!m_luaEngine) + return; + auto profile = m_luaEngine->getProfile(); if (!profile.empty()) { profile.sort([](auto const& a, auto const& b) { @@ -56,18 +84,8 @@ LuaRoot::~LuaRoot() { Logger::info("Writing lua profile {}", filename); File::writeFile(profileSummary, path); } -} -void LuaRoot::loadScript(String const& assetPath) { - m_scriptCache->loadScript(*m_luaEngine, assetPath); -} - -bool LuaRoot::scriptLoaded(String const& assetPath) const { - return m_scriptCache->scriptLoaded(assetPath); -} - -void LuaRoot::unloadScript(String const& assetPath) { - m_scriptCache->unloadScript(assetPath); + m_luaEngine.reset(); } LuaContext LuaRoot::createContext(String const& script) { @@ -91,33 +109,43 @@ LuaContext LuaRoot::createContext(StringList const& scriptPaths) { for (auto const& scriptPath : scriptPaths) cache->loadContextScript(newContext, scriptPath); + for (auto const& callbackPair : m_luaCallbacks) + newContext.setCallbacks(callbackPair.first, callbackPair.second); + return newContext; } void LuaRoot::collectGarbage(Maybe steps) { - m_luaEngine->collectGarbage(steps); + if (m_luaEngine) + m_luaEngine->collectGarbage(steps); } void LuaRoot::setAutoGarbageCollection(bool autoGarbageColleciton) { - m_luaEngine->setAutoGarbageCollection(autoGarbageColleciton); + if (m_luaEngine) + m_luaEngine->setAutoGarbageCollection(autoGarbageColleciton); } void LuaRoot::tuneAutoGarbageCollection(float pause, float stepMultiplier) { - m_luaEngine->tuneAutoGarbageCollection(pause, stepMultiplier); + if (m_luaEngine) + m_luaEngine->tuneAutoGarbageCollection(pause, stepMultiplier); } size_t LuaRoot::luaMemoryUsage() const { - return m_luaEngine->memoryUsage(); + return m_luaEngine ? m_luaEngine->memoryUsage() : 0; } size_t LuaRoot::scriptCacheMemoryUsage() const { - return m_scriptCache->memoryUsage(); + return m_luaEngine ? m_scriptCache->memoryUsage() : 0; } void LuaRoot::clearScriptCache() const { return m_scriptCache->clear(); } +void LuaRoot::addCallbacks(String const& groupName, LuaCallbacks const& callbacks) { + m_luaCallbacks[groupName] = callbacks; +} + LuaEngine& LuaRoot::luaEngine() const { return *m_luaEngine; } diff --git a/source/game/scripting/StarLuaRoot.hpp b/source/game/scripting/StarLuaRoot.hpp index 7335952..a26cf04 100644 --- a/source/game/scripting/StarLuaRoot.hpp +++ b/source/game/scripting/StarLuaRoot.hpp @@ -21,6 +21,9 @@ public: bool scriptLoaded(String const& assetPath) const; void unloadScript(String const& assetPath); + void restart(); + void shutdown(); + // A script context can be created from the combination of several scripts, // the functions / data in each script will be loaded in order, so that later // specified scripts will overwrite previous ones. @@ -39,8 +42,9 @@ public: size_t scriptCacheMemoryUsage() const; void clearScriptCache() const; - LuaEngine& luaEngine() const; + void addCallbacks(String const& groupName, LuaCallbacks const& callbacks); + LuaEngine& luaEngine() const; private: class ScriptCache { public: @@ -57,7 +61,9 @@ private: }; LuaEnginePtr m_luaEngine; + StringMap m_luaCallbacks; shared_ptr m_scriptCache; + ListenerPtr m_rootReloadListener; String m_storageDirectory; diff --git a/source/windowing/StarCanvasWidget.cpp b/source/windowing/StarCanvasWidget.cpp index 2e66759..7bff638 100644 --- a/source/windowing/StarCanvasWidget.cpp +++ b/source/windowing/StarCanvasWidget.cpp @@ -3,8 +3,7 @@ namespace Star { CanvasWidget::CanvasWidget() { - m_captureKeyboard = false; - m_captureMouse = false; + m_ignoreInterfaceScale = m_captureKeyboard = m_captureMouse = false; } void CanvasWidget::setCaptureMouseEvents(bool captureMouse) { @@ -15,6 +14,10 @@ void CanvasWidget::setCaptureKeyboardEvents(bool captureKeyboard) { m_captureKeyboard = captureKeyboard; } +void CanvasWidget::setIgnoreInterfaceScale(bool ignoreInterfaceScale) { + m_ignoreInterfaceScale = ignoreInterfaceScale; +} + void CanvasWidget::clear() { m_renderOps.clear(); } @@ -144,24 +147,33 @@ void CanvasWidget::renderImpl() { void CanvasWidget::renderImage(Vec2F const& renderingOffset, String const& texName, Vec2F const& position, float scale, Vec4B const& color, bool centered) { auto& context = GuiContext::singleton(); auto texSize = Vec2F(context.textureSize(texName)); - if (centered) { - auto screenCoords = RectF::withSize(renderingOffset * context.interfaceScale() + (position - scale * texSize / 2.0f) * context.interfaceScale(), texSize * scale * context.interfaceScale()); - context.drawQuad(texName, screenCoords, color); - } else { - auto screenCoords = RectF::withSize(renderingOffset * context.interfaceScale() + position * context.interfaceScale(), texSize * scale * context.interfaceScale()); - context.drawQuad(texName, screenCoords, color); - } + Vec2F pos = centered ? (position - scale * texSize / 2.0f) : position; + + RectF screenCoords; + if (m_ignoreInterfaceScale) + screenCoords = RectF::withSize(renderingOffset + pos, texSize * scale); + else + screenCoords = RectF::withSize(renderingOffset * context.interfaceScale() + pos * context.interfaceScale(), texSize * scale * context.interfaceScale()); + + context.drawQuad(texName, screenCoords, color); } void CanvasWidget::renderImageRect(Vec2F const& renderingOffset, String const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) { auto& context = GuiContext::singleton(); - context.drawQuad(texName, texCoords, screenCoords.scaled(context.interfaceScale()).translated(renderingOffset * context.interfaceScale()), color); + if (m_ignoreInterfaceScale) + context.drawQuad(texName, texCoords, screenCoords.translated(renderingOffset), color); + else + context.drawQuad(texName, texCoords, screenCoords.scaled(context.interfaceScale()).translated(renderingOffset * context.interfaceScale()), color); } void CanvasWidget::renderDrawable(Vec2F const& renderingOffset, Drawable drawable, Vec2F const& screenPos) { auto& context = GuiContext::singleton(); - drawable.scale(context.interfaceScale()); - context.drawDrawable(move(drawable), renderingOffset * context.interfaceScale() + screenPos * context.interfaceScale(), 1); + if (m_ignoreInterfaceScale) + context.drawDrawable(move(drawable), renderingOffset + screenPos, 1); + else { + drawable.scale(context.interfaceScale()); + context.drawDrawable(move(drawable), renderingOffset * context.interfaceScale() + screenPos * context.interfaceScale(), 1); + } } void CanvasWidget::renderTiledImage(Vec2F const& renderingOffset, String const& texName, float textureScale, Vec2D const& offset, RectF const& screenCoords, Vec4B const& color) { @@ -188,28 +200,42 @@ void CanvasWidget::renderTiledImage(Vec2F const& renderingOffset, String const& if (limitedScreenRect.isEmpty()) continue; - context.drawQuad(texName, limitedTexRect, limitedScreenRect.translated(renderingOffset).scaled(context.interfaceScale()), color); + if (m_ignoreInterfaceScale) + context.drawQuad(texName, limitedTexRect, limitedScreenRect.translated(renderingOffset), color); + else + context.drawQuad(texName, limitedTexRect, limitedScreenRect.translated(renderingOffset).scaled(context.interfaceScale()), color); } } } void CanvasWidget::renderLine(Vec2F const& renderingOffset, Vec2F const& begin, Vec2F const end, Vec4B const& color, float lineWidth) { auto& context = GuiContext::singleton(); - context.drawLine( + if (m_ignoreInterfaceScale) + context.drawLine(renderingOffset + begin, renderingOffset + end, color, lineWidth); + else { + context.drawLine( renderingOffset * context.interfaceScale() + begin * context.interfaceScale(), renderingOffset * context.interfaceScale() + end * context.interfaceScale(), color, lineWidth); + } } void CanvasWidget::renderRect(Vec2F const& renderingOffset, RectF const& coords, Vec4B const& color) { auto& context = GuiContext::singleton(); - context.drawQuad(coords.scaled(context.interfaceScale()).translated(renderingOffset * context.interfaceScale()), color); + + if (m_ignoreInterfaceScale) + context.drawQuad(coords.translated(renderingOffset), color); + else + context.drawQuad(coords.scaled(context.interfaceScale()).translated(renderingOffset * context.interfaceScale()), color); } void CanvasWidget::renderPoly(Vec2F const& renderingOffset, PolyF poly, Vec4B const& color, float lineWidth) { auto& context = GuiContext::singleton(); poly.translate(renderingOffset); - context.drawInterfacePolyLines(poly, color, lineWidth); + if (m_ignoreInterfaceScale) + context.drawPolyLines(poly, color, lineWidth); + else + context.drawInterfacePolyLines(poly, color, lineWidth); } void CanvasWidget::renderTriangles(Vec2F const& renderingOffset, List> const& triangles, Vec4B const& color) { @@ -219,7 +245,10 @@ void CanvasWidget::renderTriangles(Vec2F const& renderingOffset, List(poly) + renderingOffset, get<2>(poly) + renderingOffset); }); - context.drawInterfaceTriangles(translated, color); + if (m_ignoreInterfaceScale) + context.drawTriangles(translated, color); + else + context.drawInterfaceTriangles(translated, color); } void CanvasWidget::renderText(Vec2F const& renderingOffset, String const& s, TextPositioning const& position, unsigned fontSize, Vec4B const& color, FontMode mode, float lineSpacing, String const& font, String const& directives) { @@ -233,7 +262,10 @@ void CanvasWidget::renderText(Vec2F const& renderingOffset, String const& s, Tex TextPositioning translatedPosition = position; translatedPosition.pos += renderingOffset; - context.renderInterfaceText(s, translatedPosition); + if (m_ignoreInterfaceScale) + context.renderText(s, translatedPosition); + else + context.renderInterfaceText(s, translatedPosition); context.setDefaultLineSpacing(); context.setDefaultFont(); diff --git a/source/windowing/StarCanvasWidget.hpp b/source/windowing/StarCanvasWidget.hpp index 6f407de..3006852 100644 --- a/source/windowing/StarCanvasWidget.hpp +++ b/source/windowing/StarCanvasWidget.hpp @@ -31,6 +31,7 @@ public: void setCaptureMouseEvents(bool captureMouse); void setCaptureKeyboardEvents(bool captureKeyboard); + void setIgnoreInterfaceScale(bool ignoreInterfaceScale); // Returns mouse position relative to the lower left of the drawing region. Vec2I mousePosition() const; @@ -81,6 +82,7 @@ protected: void renderText(Vec2F const& renderingOffset, String const& s, TextPositioning const& position, unsigned fontSize, Vec4B const& color, FontMode mode, float lineSpacing, String const& font, String const& directives); private: + bool m_ignoreInterfaceScale; bool m_captureKeyboard; bool m_captureMouse; Vec2I m_mousePosition;