Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/client/StarClientApplication.cpp5
-rw-r--r--source/frontend/CMakeLists.txt2
-rw-r--r--source/frontend/StarInterfaceLuaBindings.cpp21
-rw-r--r--source/frontend/StarInterfaceLuaBindings.hpp16
-rw-r--r--source/frontend/StarMainInterface.cpp23
-rw-r--r--source/frontend/StarMainInterface.hpp5
-rw-r--r--source/frontend/StarScriptPane.cpp1
-rw-r--r--source/frontend/StarWidgetLuaBindings.cpp139
-rw-r--r--source/frontend/StarWidgetLuaBindings.hpp9
-rw-r--r--source/game/StarUniverseClient.cpp8
-rw-r--r--source/game/StarUniverseClient.hpp4
-rw-r--r--source/game/StarWorldClient.cpp11
-rw-r--r--source/game/StarWorldClient.hpp3
-rw-r--r--source/game/scripting/StarLuaRoot.cpp76
-rw-r--r--source/game/scripting/StarLuaRoot.hpp8
-rw-r--r--source/windowing/StarCanvasWidget.cpp68
-rw-r--r--source/windowing/StarCanvasWidget.hpp2
17 files changed, 288 insertions, 113 deletions
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<PlayerStorage>(m_root->toStoragePath("player"));
m_statistics = make_shared<Statistics>(m_root->toStoragePath("player"), appController()->statisticsService());
m_universeClient = make_shared<UniverseClient>(m_playerStorage, m_statistics);
+
m_mainMixer->setUniverseClient(m_universeClient);
m_titleScreen = make_shared<TitleScreen>(m_playerStorage, m_mainMixer->mixer());
if (auto renderer = Application::renderer())
@@ -596,6 +600,7 @@ void ClientApplication::changeState(MainAppState newState) {
m_worldPainter = make_shared<WorldPainter>();
m_mainInterface = make_shared<MainInterface>(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<CanvasWidgetPtr> {
+ 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<CanvasWidget>()).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<EntityId, PanePtr> m_interactionScriptPanes;
+ StringMap<CanvasWidgetPtr> 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<CanvasWidgetPtr> : LuaUserDataConverter<CanvasWidgetPtr> {};
-
-template <>
-struct LuaUserDataMethods<CanvasWidgetPtr> {
- static LuaMethods<CanvasWidgetPtr> make() {
- LuaMethods<CanvasWidgetPtr> methods;
-
- methods.registerMethodWithSignature<Vec2I, CanvasWidgetPtr>("size", mem_fn(&CanvasWidget::size));
- methods.registerMethodWithSignature<Vec2I, CanvasWidgetPtr>("mousePosition", mem_fn(&CanvasWidget::mousePosition));
-
- methods.registerMethodWithSignature<void, CanvasWidgetPtr>("clear", mem_fn(&CanvasWidget::clear));
-
- methods.registerMethod("drawImage",
- [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, Maybe<float> scale, Maybe<Color> color, Maybe<bool> 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<Vec2F, float> scale, Maybe<Color> color, Maybe<float> rotation) {
- auto drawable = Drawable::makeImage(image, 1.0, true, {0.0, 0.0}, color.value(Color::White));
- if (auto s = scale.maybe<Vec2F>())
- drawable.transform(Mat3F::scaling(*s));
- else if(auto s = scale.maybe<float>())
- 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> color) {
- canvasWidget->drawImageRect(image, texCoords, screenCoords, color.value(Color::White).toRgba());
- });
- methods.registerMethod("drawTiledImage",
- [](CanvasWidgetPtr canvasWidget, String image, Vec2D offset, RectF screenCoords, Maybe<float> scale, Maybe<Color> 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> color, Maybe<float> lineWidth) {
- canvasWidget->drawLine(begin, end, color.value(Color::White).toRgba(), lineWidth.value(1.0f));
- });
- methods.registerMethod("drawRect",
- [](CanvasWidgetPtr canvasWidget, RectF rect, Maybe<Color> color) {
- canvasWidget->drawRect(rect, color.value(Color::White).toRgba());
- });
- methods.registerMethod("drawPoly",
- [](CanvasWidgetPtr canvasWidget, PolyF poly, Maybe<Color> color, Maybe<float> lineWidth) {
- canvasWidget->drawPoly(poly, color.value(Color::White).toRgba(), lineWidth.value(1.0f));
- });
- methods.registerMethod("drawTriangles",
- [](CanvasWidgetPtr canvasWidget, List<PolyF> triangles, Maybe<Color> color) {
- auto tris = triangles.transformed([](PolyF const& poly) {
- if (poly.sides() != 3)
- throw StarException("Triangle must have exactly 3 sides");
- return tuple<Vec2F, Vec2F, Vec2F>(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> color, Maybe<float> lineSpacing, Maybe<String> font, Maybe<String> directives) {
- canvasWidget->drawText(text, TextPositioning(tp), fontSize, color.value(Color::White).toRgba(), FontMode::Normal, lineSpacing.value(DefaultLineSpacing), font.value(""), directives.value(""));
- });
-
- return methods;
- }
-};
+LuaMethods<CanvasWidgetPtr> LuaUserDataMethods<CanvasWidgetPtr>::make() {
+ LuaMethods<CanvasWidgetPtr> methods;
+
+ methods.registerMethodWithSignature<Vec2I, CanvasWidgetPtr>("size", mem_fn(&CanvasWidget::size));
+ methods.registerMethodWithSignature<Vec2I, CanvasWidgetPtr>("mousePosition", mem_fn(&CanvasWidget::mousePosition));
+
+ methods.registerMethodWithSignature<void, CanvasWidgetPtr>("clear", mem_fn(&CanvasWidget::clear));
+
+ methods.registerMethod("drawDrawable", [](CanvasWidgetPtr canvasWidget, Drawable drawable) {
+ canvasWidget->drawDrawable(move(drawable), Vec2F());
+ });
+
+ methods.registerMethod("drawDrawables", [](CanvasWidgetPtr canvasWidget, List<Drawable> drawables) {
+ for (auto& drawable : drawables)
+ canvasWidget->drawDrawable(move(drawable), Vec2F());
+ });
+
+ methods.registerMethod("drawImage",
+ [](CanvasWidgetPtr canvasWidget, String image, Vec2F position, Maybe<float> scale, Maybe<Color> color, Maybe<bool> 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<Vec2F, float> scale, Maybe<Color> color, Maybe<float> rotation) {
+ auto drawable = Drawable::makeImage(image, 1.0, true, {0.0, 0.0}, color.value(Color::White));
+ if (auto s = scale.maybe<Vec2F>())
+ drawable.transform(Mat3F::scaling(*s));
+ else if(auto s = scale.maybe<float>())
+ 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> color) {
+ canvasWidget->drawImageRect(image, texCoords, screenCoords, color.value(Color::White).toRgba());
+ });
+ methods.registerMethod("drawTiledImage",
+ [](CanvasWidgetPtr canvasWidget, String image, Vec2D offset, RectF screenCoords, Maybe<float> scale, Maybe<Color> 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> color, Maybe<float> lineWidth) {
+ canvasWidget->drawLine(begin, end, color.value(Color::White).toRgba(), lineWidth.value(1.0f));
+ });
+ methods.registerMethod("drawRect",
+ [](CanvasWidgetPtr canvasWidget, RectF rect, Maybe<Color> color) {
+ canvasWidget->drawRect(rect, color.value(Color::White).toRgba());
+ });
+ methods.registerMethod("drawPoly",
+ [](CanvasWidgetPtr canvasWidget, PolyF poly, Maybe<Color> color, Maybe<float> lineWidth) {
+ canvasWidget->drawPoly(poly, color.value(Color::White).toRgba(), lineWidth.value(1.0f));
+ });
+ methods.registerMethod("drawTriangles",
+ [](CanvasWidgetPtr canvasWidget, List<PolyF> triangles, Maybe<Color> color) {
+ auto tris = triangles.transformed([](PolyF const& poly) {
+ if (poly.sides() != 3)
+ throw StarException("Triangle must have exactly 3 sides");
+ return tuple<Vec2F, Vec2F, Vec2F>(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> color, Maybe<float> lineSpacing, Maybe<String> font, Maybe<String> 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<CanvasWidgetPtr> : LuaUserDataConverter<CanvasWidgetPtr> {};
+
+template <>
+struct LuaUserDataMethods<CanvasWidgetPtr> {
+ static LuaMethods<CanvasWidgetPtr> 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<String> UniverseClient::connect(UniverseConnection connection, bool allowA
m_mainPlayer->setClientContext(m_clientContext);
m_mainPlayer->setStatistics(m_statistics);
m_worldClient = make_shared<WorldClient>(m_mainPlayer);
+ for (auto& pair : m_luaCallbacks)
+ m_worldClient->setLuaCallbacks(pair.first, pair.second);
m_connection = move(connection);
m_celestialDatabase = make_shared<CelestialSlaveDatabase>(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<UniverseConnection> m_connection;
Maybe<ServerInfo> m_serverInfo;
+
+ StringMap<LuaCallbacks> 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<LuaRoot>();
+
m_mainPlayer = mainPlayer;
centerClientWindowOnPlayer(Vec2U(100, 100));
@@ -895,6 +897,10 @@ List<PacketPtr> 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<EntityMap>(m_worldTemplate->size(), entitySpace.first, entitySpace.second);
m_tileArray = make_shared<ClientTileSectorArray>(m_worldTemplate->size());
m_damageManager = make_shared<DamageManager>(this, startPacket.clientId);
- m_luaRoot = make_shared<LuaRoot>();
+ 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<PacketPtr> const& packets);
List<PacketPtr> 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<ScriptCache>();
+ restart();
+
m_rootReloadListener = make_shared<CallbackListener>([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<unsigned> 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<LuaCallbacks> m_luaCallbacks;
shared_ptr<ScriptCache> 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<tuple<Vec2F, Vec2F, Vec2F>> const& triangles, Vec4B const& color) {
@@ -219,7 +245,10 @@ void CanvasWidget::renderTriangles(Vec2F const& renderingOffset, List<tuple<Vec2
get<1>(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;