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

summaryrefslogtreecommitdiff
path: root/source/windowing
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-07-04 22:36:27 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-07-04 22:36:27 +1000
commitc923f4f13b1cade968bb6fec585a242b62d35715 (patch)
tree94bc9f9098c007070d3644f077e6f544c4fd43a4 /source/windowing
parent5df9adcd0ecbf09ae2ba426b3eeab78296d370c4 (diff)
pane lua stuff
Diffstat (limited to 'source/windowing')
-rw-r--r--source/windowing/CMakeLists.txt2
-rw-r--r--source/windowing/StarGuiReader.hpp1
-rw-r--r--source/windowing/StarListWidget.hpp1
-rw-r--r--source/windowing/StarPane.cpp131
-rw-r--r--source/windowing/StarPane.hpp7
-rw-r--r--source/windowing/StarRegisteredPaneManager.hpp10
-rw-r--r--source/windowing/StarWidgetLuaBindings.cpp417
-rw-r--r--source/windowing/StarWidgetLuaBindings.hpp26
8 files changed, 564 insertions, 31 deletions
diff --git a/source/windowing/CMakeLists.txt b/source/windowing/CMakeLists.txt
index 18e035d..5db1ce6 100644
--- a/source/windowing/CMakeLists.txt
+++ b/source/windowing/CMakeLists.txt
@@ -38,6 +38,7 @@ SET (star_windowing_HEADERS
StarTextBoxWidget.hpp
StarVerticalLayout.hpp
StarWidget.hpp
+ StarWidgetLuaBindings.hpp
StarWidgetParsing.hpp
)
@@ -70,6 +71,7 @@ SET (star_windowing_SOURCES
StarTextBoxWidget.cpp
StarVerticalLayout.cpp
StarWidget.cpp
+ StarWidgetLuaBindings.cpp
StarWidgetParsing.cpp
)
diff --git a/source/windowing/StarGuiReader.hpp b/source/windowing/StarGuiReader.hpp
index f42a037..e031f62 100644
--- a/source/windowing/StarGuiReader.hpp
+++ b/source/windowing/StarGuiReader.hpp
@@ -6,6 +6,7 @@
namespace Star {
STAR_EXCEPTION(GUIBuilderException, StarException);
+STAR_CLASS(GuiReader);
class GuiReader : public WidgetParser {
public:
diff --git a/source/windowing/StarListWidget.hpp b/source/windowing/StarListWidget.hpp
index 8f511e3..8bb63db 100644
--- a/source/windowing/StarListWidget.hpp
+++ b/source/windowing/StarListWidget.hpp
@@ -6,7 +6,6 @@
namespace Star {
-STAR_CLASS(GuiReader);
STAR_CLASS(ListWidget);
class ListWidget : public Widget {
diff --git a/source/windowing/StarPane.cpp b/source/windowing/StarPane.cpp
index 69cbabf..a2d32ad 100644
--- a/source/windowing/StarPane.cpp
+++ b/source/windowing/StarPane.cpp
@@ -2,6 +2,10 @@
#include "StarRoot.hpp"
#include "StarJsonExtra.hpp"
#include "StarAssets.hpp"
+#include "StarWidgetLuaBindings.hpp"
+#include "StarLuaConverters.hpp"
+#include "StarImageWidget.hpp"
+#include "StarGuiReader.hpp"
namespace Star {
@@ -187,35 +191,6 @@ Pane* Pane::window() {
return this;
}
-void Pane::renderImpl() {
- if (m_bgFooter != "")
- m_context->drawInterfaceQuad(m_bgFooter, Vec2F(position()));
-
- if (m_bgBody != "")
- m_context->drawInterfaceQuad(m_bgBody, Vec2F(position()) + Vec2F(0, m_footerSize[1]));
-
- if (m_bgHeader != "") {
- auto headerPos = Vec2F(position()) + Vec2F(0, m_footerSize[1] + m_bodySize[1]);
- m_context->drawInterfaceQuad(m_bgHeader, headerPos);
-
- if (m_icon) {
- m_icon->setPosition(Vec2I(0, m_footerSize[1] + m_bodySize[1]) + m_iconOffset);
- m_icon->render(m_drawingArea);
- m_context->resetInterfaceScissorRect();
- }
-
- m_context->setFont(m_font);
- m_context->setFontSize(m_fontSize);
- m_context->setFontColor(m_titleColor.toRgba());
- m_context->setFontMode(FontMode::Shadow);
- m_context->renderInterfaceText(m_title, {headerPos + Vec2F(m_titleOffset)});
- m_context->setFontColor(m_subTitleColor.toRgba());
- m_context->renderInterfaceText(m_subTitle, {headerPos + Vec2F(m_subTitleOffset)});
- m_context->setFontMode(FontMode::Normal);
- m_context->setDefaultFont();
- }
-}
-
void Pane::update() {
if (m_visible) {
for (auto const& widget : m_members) {
@@ -228,7 +203,11 @@ void Pane::update() {
}
}
-void Pane::tick() {}
+void Pane::tick() {
+ m_playingSounds.filter([](pair<String, AudioInstancePtr> const& p) {
+ return p.second->finished() == false;
+ });
+}
bool Pane::dragActive() const {
return m_dragActive;
@@ -369,4 +348,96 @@ Maybe<String> Pane::cursorOverride(Vec2I const&) {
return {};
}
+LuaCallbacks Pane::makePaneCallbacks() {
+ LuaCallbacks callbacks;
+
+ callbacks.registerCallback("toWidget", [this]() -> LuaCallbacks {
+ return LuaBindings::makeWidgetCallbacks(this, reader());
+ });
+
+ callbacks.registerCallback("dismiss", [this]() { dismiss(); });
+
+ callbacks.registerCallback("playSound",
+ [this](String const& audio, Maybe<int> loops, Maybe<float> volume) {
+ auto assets = Root::singleton().assets();
+ auto config = Root::singleton().configuration();
+ auto audioInstance = make_shared<AudioInstance>(*assets->audio(audio));
+ audioInstance->setVolume(volume.value(1.0));
+ audioInstance->setLoops(loops.value(0));
+ auto& guiContext = GuiContext::singleton();
+ guiContext.playAudio(audioInstance);
+ m_playingSounds.append({audio, move(audioInstance)});
+ });
+
+ callbacks.registerCallback("stopAllSounds", [this](Maybe<String> const& audio) {
+ m_playingSounds.filter([audio](pair<String, AudioInstancePtr> const& p) {
+ if (!audio || p.first == *audio) {
+ p.second->stop();
+ return false;
+ }
+ return true;
+ });
+ });
+
+ callbacks.registerCallback("setTitle", [this](String const& title, String const& subTitle) {
+ setTitleString(title, subTitle);
+ });
+
+ callbacks.registerCallback("setTitleIcon", [this](String const& image) {
+ if (auto icon = as<ImageWidget>(titleIcon()))
+ icon->setImage(image);
+ });
+
+ callbacks.registerCallback("getPosition", [this]() -> Vec2I { return relativePosition(); });
+ callbacks.registerCallback("setPosition", [this](Vec2I const& position) { setPosition(position); });
+ callbacks.registerCallback("getSize", [this]() -> Vec2I { return size(); });
+ callbacks.registerCallback("setSize", [this](Vec2I const& size) { setSize(size); });
+
+ callbacks.registerCallback("addWidget", [this](Json const& newWidgetConfig, Maybe<String> const& newWidgetName) -> LuaCallbacks {
+ String name = newWidgetName.value(toString(Random::randu64()));
+ WidgetPtr newWidget = reader()->makeSingle(name, newWidgetConfig);
+ this->addChild(name, newWidget);
+ return LuaBindings::makeWidgetCallbacks(newWidget.get(), reader());
+ });
+
+ callbacks.registerCallback("removeWidget", [this](String const& widgetName) -> bool {
+ return this->removeChild(widgetName);
+ });
+
+ return callbacks;
+}
+
+GuiReaderPtr Pane::reader() {
+ return make_shared<GuiReader>();
+}
+
+void Pane::renderImpl() {
+ if (m_bgFooter != "")
+ m_context->drawInterfaceQuad(m_bgFooter, Vec2F(position()));
+
+ if (m_bgBody != "")
+ m_context->drawInterfaceQuad(m_bgBody, Vec2F(position()) + Vec2F(0, m_footerSize[1]));
+
+ if (m_bgHeader != "") {
+ auto headerPos = Vec2F(position()) + Vec2F(0, m_footerSize[1] + m_bodySize[1]);
+ m_context->drawInterfaceQuad(m_bgHeader, headerPos);
+
+ if (m_icon) {
+ m_icon->setPosition(Vec2I(0, m_footerSize[1] + m_bodySize[1]) + m_iconOffset);
+ m_icon->render(m_drawingArea);
+ m_context->resetInterfaceScissorRect();
+ }
+
+ m_context->setFont(m_font);
+ m_context->setFontSize(m_fontSize);
+ m_context->setFontColor(m_titleColor.toRgba());
+ m_context->setFontMode(FontMode::Shadow);
+ m_context->renderInterfaceText(m_title, {headerPos + Vec2F(m_titleOffset)});
+ m_context->setFontColor(m_subTitleColor.toRgba());
+ m_context->renderInterfaceText(m_subTitle, {headerPos + Vec2F(m_subTitleOffset)});
+ m_context->setFontMode(FontMode::Normal);
+ m_context->setDefaultFont();
+ }
+}
+
}
diff --git a/source/windowing/StarPane.hpp b/source/windowing/StarPane.hpp
index ce78337..7a466b4 100644
--- a/source/windowing/StarPane.hpp
+++ b/source/windowing/StarPane.hpp
@@ -7,6 +7,9 @@
namespace Star {
STAR_CLASS(Pane);
+STAR_CLASS(LuaCallbacks);
+STAR_CLASS(AudioInstance);
+STAR_CLASS(GuiReader);
enum class PaneAnchor {
None,
@@ -89,7 +92,9 @@ public:
virtual PanePtr createTooltip(Vec2I const& screenPosition);
virtual Maybe<String> cursorOverride(Vec2I const& screenPosition);
+ virtual LuaCallbacks makePaneCallbacks();
protected:
+ virtual GuiReaderPtr reader();
virtual void renderImpl();
String m_bgHeader;
@@ -124,6 +129,8 @@ protected:
PaneAnchor m_anchor;
Vec2I m_anchorOffset;
bool m_hasDisplayed;
+
+ List<pair<String, AudioInstancePtr>> m_playingSounds;
};
}
diff --git a/source/windowing/StarRegisteredPaneManager.hpp b/source/windowing/StarRegisteredPaneManager.hpp
index 4038525..ebb158d 100644
--- a/source/windowing/StarRegisteredPaneManager.hpp
+++ b/source/windowing/StarRegisteredPaneManager.hpp
@@ -19,6 +19,8 @@ public:
template <typename T = Pane>
shared_ptr<T> registeredPane(KeyT const& paneId) const;
+ template <typename T = Pane>
+ shared_ptr<T> maybeRegisteredPane(KeyT const& paneId) const;
// Displays a registred pane if it is not already displayed. Returns true
// if it is newly displayed.
@@ -54,6 +56,14 @@ shared_ptr<T> RegisteredPaneManager<KeyT>::registeredPane(KeyT const& paneId) co
}
template <typename KeyT>
+template <typename T>
+shared_ptr<T> RegisteredPaneManager<KeyT>::maybeRegisteredPane(KeyT const& paneId) const {
+ if (auto v = m_registeredPanes.ptr(paneId))
+ return convert<T>(v->pane);
+ return {};
+}
+
+template <typename KeyT>
void RegisteredPaneManager<KeyT>::registerPane(
KeyT paneId, PaneLayer paneLayer, PanePtr pane, DismissCallback onDismiss) {
if (!m_registeredPanes.insert(move(paneId), {move(paneLayer), move(pane), move(onDismiss)}).second)
diff --git a/source/windowing/StarWidgetLuaBindings.cpp b/source/windowing/StarWidgetLuaBindings.cpp
new file mode 100644
index 0000000..62d2be6
--- /dev/null
+++ b/source/windowing/StarWidgetLuaBindings.cpp
@@ -0,0 +1,417 @@
+#include "StarWidgetLuaBindings.hpp"
+#include "StarJsonExtra.hpp"
+#include "StarLuaGameConverters.hpp"
+#include "StarGuiReader.hpp"
+#include "StarCanvasWidget.hpp"
+#include "StarLabelWidget.hpp"
+#include "StarListWidget.hpp"
+#include "StarButtonWidget.hpp"
+#include "StarButtonGroup.hpp"
+#include "StarTextBoxWidget.hpp"
+#include "StarProgressWidget.hpp"
+#include "StarSliderBar.hpp"
+#include "StarItemGridWidget.hpp"
+#include "StarItemSlotWidget.hpp"
+#include "StarItemDatabase.hpp"
+#include "StarFlowLayout.hpp"
+
+namespace Star {
+
+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, GuiReaderPtr reader) {
+ if (!reader)
+ reader = make_shared<GuiReader>();
+
+ LuaCallbacks callbacks;
+
+ // a bit miscellaneous, but put this here since widgets have access to gui context
+
+ callbacks.registerCallback("playSound",
+ [parentWidget](String const& audio, Maybe<int> loops, Maybe<float> volume) {
+ parentWidget->context()->playAudio(audio, loops.value(0), volume.value(1.0f));
+ });
+
+ // widget userdata methods
+
+ callbacks.registerCallback("bindCanvas", [parentWidget](String const& widgetName) -> Maybe<CanvasWidgetPtr> {
+ if (auto canvas = parentWidget->fetchChild<CanvasWidget>(widgetName))
+ return canvas;
+ return {};
+ });
+
+ // generic widget callbacks
+
+ callbacks.registerCallback("getPosition", [parentWidget](String const& widgetName) -> Maybe<Vec2I> {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->relativePosition();
+ return {};
+ });
+ callbacks.registerCallback("setPosition", [parentWidget](String const& widgetName, Vec2I const& position) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->setPosition(position);
+ });
+
+ callbacks.registerCallback("getSize", [parentWidget](String const& widgetName) -> Maybe<Vec2I> {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->size();
+ return {};
+ });
+ callbacks.registerCallback("setSize", [parentWidget](String const& widgetName, Vec2I const& size) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->setSize(size);
+ });
+
+ callbacks.registerCallback("setVisible", [parentWidget](String const& widgetName, bool visible) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->setVisibility(visible);
+ });
+
+ callbacks.registerCallback("active", [parentWidget](String const& widgetName) -> Maybe<bool> {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->active();
+ return {};
+ });
+
+ callbacks.registerCallback("focus", [parentWidget](String const& widgetName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->focus();
+ });
+
+ callbacks.registerCallback("hasFocus", [parentWidget](String const& widgetName) -> Maybe<bool> {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->hasFocus();
+ return {};
+ });
+
+ callbacks.registerCallback("blur", [parentWidget](String const& widgetName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->blur();
+ });
+
+ callbacks.registerCallback("getData", [parentWidget](String const& widgetName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->data();
+ return Json();
+ });
+
+ callbacks.registerCallback("setData", [parentWidget](String const& widgetName, Json const& data) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->setData(data);
+ });
+
+ callbacks.registerCallback("getChildAt", [parentWidget](Vec2I const& screenPosition) -> Maybe<String> {
+ if (auto widget = parentWidget->getChildAt(screenPosition))
+ return widget->fullName();
+ else
+ return{};
+ });
+
+ callbacks.registerCallback("inMember", [parentWidget](String const& widgetName, Vec2I const& screenPosition) -> Maybe<bool> {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ return widget->inMember(screenPosition);
+ else
+ return {};
+ });
+
+ callbacks.registerCallback("addChild", [parentWidget, reader](String const& widgetName, Json const& newChildConfig, Maybe<String> const& newChildName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName)) {
+ String name = newChildName.value(strf("{}", Random::randu64()));
+ WidgetPtr newChild = reader->makeSingle(name, newChildConfig);
+ widget->addChild(name, newChild);
+ }
+ });
+
+ callbacks.registerCallback("removeAllChildren", [parentWidget](String const& widgetName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->removeAllChildren();
+ });
+
+ callbacks.registerCallback("removeChild", [parentWidget](String const& widgetName, String const& childName) {
+ if (auto widget = parentWidget->fetchChild<Widget>(widgetName))
+ widget->removeChild(childName);
+ });
+
+ // callbacks only valid for specific widget types
+
+ callbacks.registerCallback("getText", [parentWidget](String const& widgetName) -> Maybe<String> {
+ if (auto textBox = parentWidget->fetchChild<TextBoxWidget>(widgetName))
+ return textBox->getText();
+ return {};
+ });
+
+ callbacks.registerCallback("setText", [parentWidget](String const& widgetName, String const& text) {
+ if (auto label = parentWidget->fetchChild<LabelWidget>(widgetName))
+ label->setText(text);
+ else if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setText(text);
+ else if (auto textBox = parentWidget->fetchChild<TextBoxWidget>(widgetName))
+ textBox->setText(text);
+ });
+
+ callbacks.registerCallback("setFontColor", [parentWidget](String const& widgetName, Color const& color) {
+ if (auto label = parentWidget->fetchChild<LabelWidget>(widgetName))
+ label->setColor(color);
+ else if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setFontColor(color);
+ else if (auto textBox = parentWidget->fetchChild<TextBoxWidget>(widgetName))
+ textBox->setColor(color);
+ });
+
+ callbacks.registerCallback("setImage", [parentWidget](String const& widgetName, String const& imagePath) {
+ if (auto image = parentWidget->fetchChild<ImageWidget>(widgetName))
+ image->setImage(imagePath);
+ });
+
+ callbacks.registerCallback("setImageScale", [parentWidget](String const& widgetName, float const& imageScale) {
+ if (auto image = parentWidget->fetchChild<ImageWidget>(widgetName))
+ image->setScale(imageScale);
+ });
+
+ callbacks.registerCallback("setImageRotation", [parentWidget](String const& widgetName, float const& imageRotation) {
+ if (auto image = parentWidget->fetchChild<ImageWidget>(widgetName))
+ image->setRotation(imageRotation);
+ });
+
+ callbacks.registerCallback("setButtonEnabled", [parentWidget](String const& widgetName, bool enabled) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setEnabled(enabled);
+ });
+
+ callbacks.registerCallback("setButtonImage", [parentWidget](String const& widgetName, String const& baseImage) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setImages(baseImage);
+ });
+
+ callbacks.registerCallback("setButtonImages", [parentWidget](String const& widgetName, Json const& imageSet) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setImages(imageSet.getString("base"), imageSet.getString("hover", ""), imageSet.getString("pressed", ""), imageSet.getString("disabled", ""));
+ });
+
+ callbacks.registerCallback("setButtonCheckedImages", [parentWidget](String const& widgetName, Json const& imageSet) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setCheckedImages(imageSet.getString("base"), imageSet.getString("hover", ""), imageSet.getString("pressed", ""), imageSet.getString("disabled", ""));
+ });
+
+ callbacks.registerCallback("setButtonOverlayImage", [parentWidget](String const& widgetName, String const& overlayImage) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setOverlayImage(overlayImage);
+ });
+
+ callbacks.registerCallback("getChecked", [parentWidget](String const& widgetName) -> Maybe<bool> {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ return button->isChecked();
+ return {};
+ });
+
+ callbacks.registerCallback("setChecked", [parentWidget](String const& widgetName, bool checked) {
+ if (auto button = parentWidget->fetchChild<ButtonWidget>(widgetName))
+ button->setChecked(checked);
+ });
+
+ callbacks.registerCallback("getSelectedOption", [parentWidget](String const& widgetName) -> Maybe<int> {
+ if (auto buttonGroup = parentWidget->fetchChild<ButtonGroupWidget>(widgetName))
+ return buttonGroup->checkedId();
+ return {};
+ });
+
+ callbacks.registerCallback("getSelectedData", [parentWidget](String const& widgetName) -> Json {
+ if (auto buttonGroup = parentWidget->fetchChild<ButtonGroupWidget>(widgetName)) {
+ if (auto button = buttonGroup->checkedButton())
+ return button->data();
+ }
+ return {};
+ });
+
+ callbacks.registerCallback("setSelectedOption", [parentWidget](String const& widgetName, Maybe<int> index) {
+ if (auto buttonGroup = parentWidget->fetchChild<ButtonGroupWidget>(widgetName))
+ buttonGroup->select(index.value(ButtonGroup::NoButton));
+ });
+
+ callbacks.registerCallback("setOptionEnabled", [parentWidget](String const& widgetName, int index, bool enabled) {
+ if (auto buttonGroup = parentWidget->fetchChild<ButtonGroupWidget>(widgetName)) {
+ if (auto button = buttonGroup->button(index))
+ button->setEnabled(enabled);
+ }
+ });
+
+ callbacks.registerCallback("setOptionVisible", [parentWidget](String const& widgetName, int index, bool visible) {
+ if (auto buttonGroup = parentWidget->fetchChild<ButtonGroupWidget>(widgetName)) {
+ if (auto button = buttonGroup->button(index))
+ button->setVisibility(visible);
+ }
+ });
+
+ callbacks.registerCallback("setProgress", [parentWidget](String const& widgetName, float const& value) {
+ if (auto progress = parentWidget->fetchChild<ProgressWidget>(widgetName))
+ progress->setCurrentProgressLevel(value);
+ });
+
+ callbacks.registerCallback("setSliderEnabled", [parentWidget](String const& widgetName, bool enabled) {
+ if (auto slider = parentWidget->fetchChild<SliderBarWidget>(widgetName))
+ slider->setEnabled(enabled);
+ });
+
+ callbacks.registerCallback("getSliderValue", [parentWidget](String const& widgetName) -> Maybe<int> {
+ if (auto slider = parentWidget->fetchChild<SliderBarWidget>(widgetName))
+ return slider->val();
+ return {};
+ });
+
+ callbacks.registerCallback("setSliderValue", [parentWidget](String const& widgetName, int newValue) {
+ if (auto slider = parentWidget->fetchChild<SliderBarWidget>(widgetName))
+ return slider->setVal(newValue);
+ });
+
+ callbacks.registerCallback("setSliderRange", [parentWidget](String const& widgetName, int newMin, int newMax, Maybe<int> newDelta) {
+ if (auto slider = parentWidget->fetchChild<SliderBarWidget>(widgetName))
+ return slider->setRange(newMin, newMax, newDelta.value(1));
+ });
+
+ callbacks.registerCallback("clearListItems", [parentWidget](String const& widgetName) {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName))
+ list->clear();
+ });
+
+ callbacks.registerCallback("addListItem", [parentWidget](String const& widgetName) -> Maybe<String> {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName)) {
+ auto newItem = list->addItem();
+ return newItem->name();
+ }
+ return {};
+ });
+
+ callbacks.registerCallback("removeListItem", [parentWidget](String const& widgetName, size_t at) {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName))
+ list->removeItem(at);
+ });
+
+ callbacks.registerCallback("getListSelected", [parentWidget](String const& widgetName) -> Maybe<String> {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName))
+ if (list->selectedItem() != NPos)
+ return list->selectedWidget()->name();
+ return {};
+ });
+
+ callbacks.registerCallback("setListSelected", [parentWidget](String const& widgetName, String const& selectedName) {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName))
+ if (auto selected = list->fetchChild(selectedName))
+ list->setSelectedWidget(selected);
+ });
+
+ callbacks.registerCallback("registerMemberCallback", [parentWidget](String const& widgetName, String const& name, LuaFunction callback) {
+ if (auto list = parentWidget->fetchChild<ListWidget>(widgetName)){
+ list->registerMemberCallback(name, [callback](Widget* widget) {
+ callback.invoke(widget->name(), widget->data());
+ });
+ }
+ });
+
+ callbacks.registerCallback("itemGridItems", [parentWidget](String const& widgetName) {
+ if (auto itemGrid = parentWidget->fetchChild<ItemGridWidget>(widgetName))
+ return itemGrid->bag()->toJson();
+ return Json();
+ });
+
+ callbacks.registerCallback("itemSlotItem", [parentWidget](String const& widgetName) -> Maybe<Json> {
+ if (auto itemSlot = parentWidget->fetchChild<ItemSlotWidget>(widgetName)) {
+ if (itemSlot->item())
+ return itemSlot->item()->descriptor().toJson();
+ }
+ return {};
+ });
+
+ callbacks.registerCallback("setItemSlotItem", [parentWidget](String const& widgetName, Json const& item) {
+ if (auto itemSlot = parentWidget->fetchChild<ItemSlotWidget>(widgetName)) {
+ auto itemDb = Root::singleton().itemDatabase();
+ itemSlot->setItem(itemDb->fromJson(item));
+ }
+ });
+
+ callbacks.registerCallback("setItemSlotProgress", [parentWidget](String const& widgetName, float progress) {
+ if (auto itemSlot = parentWidget->fetchChild<ItemSlotWidget>(widgetName)) {
+ itemSlot->setProgress(progress);
+ }
+ });
+
+ callbacks.registerCallback("addFlowImage", [parentWidget](String const& widgetName, String const& childName, String const& image) {
+ if (auto flow = parentWidget->fetchChild<FlowLayout>(widgetName)) {
+ WidgetPtr newChild = make_shared<ImageWidget>(image);
+ flow->addChild(childName, newChild);
+ }
+ });
+
+ return callbacks;
+}
+
+}
diff --git a/source/windowing/StarWidgetLuaBindings.hpp b/source/windowing/StarWidgetLuaBindings.hpp
new file mode 100644
index 0000000..d133760
--- /dev/null
+++ b/source/windowing/StarWidgetLuaBindings.hpp
@@ -0,0 +1,26 @@
+#ifndef STAR_WIDGET_LUA_BINDINGS_HPP
+#define STAR_WIDGET_LUA_BINDINGS_HPP
+
+#include "StarLua.hpp"
+#include "StarGuiReader.hpp"
+
+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, GuiReaderPtr reader = {});
+}
+
+}
+
+#endif