diff --git a/extra/DefaultTheme.oss b/extra/DefaultTheme.oss index 78a84f6..4a5a804 100644 --- a/extra/DefaultTheme.oss +++ b/extra/DefaultTheme.oss @@ -156,7 +156,6 @@ window.backgroundColor = rgba(160, 160, 160, 255) } % ==================== - (image) { path = file("img.png") animated = true @@ -166,14 +165,11 @@ window.backgroundColor = rgba(160, 160, 160, 255) rows: 4, \ frameWidth: 256, \ frameHeight: 256) - backgroundColor = #999999FF - backgroundGradient = gradientV(rgb(160, 160, 160) - rgb(120, 120, 120)) + useBackgroundGradient = true + backgroundGradient = gradientV(color_crimson - $accentColorDark) + showBorder = true + borderWidth = 1 borderColor = $accentColorDark borderRadius = 0 - borderWidth = 1 - showBackground = true - showBorder = true - useBackgroundGradient = true - padding = rect(15, 8, 15, 8) - margin = rect(0, 0, 0, 0) + padding = rect(15, 15, 15, 15) } diff --git a/other/TODO.txt b/other/TODO.txt index 136f63d..5639c2a 100644 --- a/other/TODO.txt +++ b/other/TODO.txt @@ -25,6 +25,8 @@ Implement cursors in Stylesheet FIX: Window getting exponentially bigger when Desktop scale changes FIX: Refreshing scroll when content extent changes Add Dark Mode Default theme +FIX: Float values in stylesheet needing to have decimal point to be read as float +Make parsing of vec2 and rect in stylesheet, consistent with other value functions like gradients and animations @@ -34,14 +36,14 @@ Implement following widgets: ***Panel / Container ***Title Label ***ScrollView - Button + ***Image / Icon + ***Button Image/Icon Radio Button Grouping Text Input Horizontal Slider Vertical Slider - Image / Icon ListBox ComboBox TreeView diff --git a/other/build.nr b/other/build.nr index 9527c05..4adb23b 100644 --- a/other/build.nr +++ b/other/build.nr @@ -1 +1 @@ -2071 +2072 diff --git a/src/ogfx/gui/Window.hpp b/src/ogfx/gui/Window.hpp index d09d478..d38ba88 100644 --- a/src/ogfx/gui/Window.hpp +++ b/src/ogfx/gui/Window.hpp @@ -105,6 +105,7 @@ namespace ogfx inline ostd::Stylesheet::VariableList& getDefaultStylesheetVariableList(void) { return m_defaultStylesheetVariables; } inline virtual void setTheme(const ostd::Stylesheet& theme) { } + inline BasicRenderer2D& getGFX(void) { return m_gfx; } inline bool isInitialized(void) const { return m_initialized; } inline bool isRunning(void) const { return m_running; } inline bool isVisible(void) const { return m_visible; } @@ -145,6 +146,7 @@ namespace ogfx protected: SDL_Window* m_window { nullptr }; SDL_Renderer* m_renderer { nullptr }; + BasicRenderer2D m_gfx; ostd::ConsoleOutputHandler m_out; GraphicsWindowOutputHandler m_wout; const ostd::Stylesheet* m_guiTheme { nullptr }; @@ -263,7 +265,6 @@ namespace ogfx void __on_fixed_update(void) override; protected: - BasicRenderer2D m_gfx; widgets::RootWidget m_rootWidget { *this }; ostd::StepTimer m_fixedUpdateTimer; ostd::StepTimer::TimePoint m_lastFrameTime; diff --git a/src/ogfx/gui/widgets/Label.cpp b/src/ogfx/gui/widgets/Label.cpp index ee0dfcb..51e20b4 100644 --- a/src/ogfx/gui/widgets/Label.cpp +++ b/src/ogfx/gui/widgets/Label.cpp @@ -20,6 +20,8 @@ #include "Label.hpp" #include "../../render/BasicRenderer.hpp" +#include "../../../ostd/io/FileSystem.hpp" +#include "../Window.hpp" namespace ogfx { @@ -62,6 +64,62 @@ namespace ogfx setSize({ cast(size.x), cast(size.y) }); m_textChanged = false; } + + + + + ImageLabel& ImageLabel::create(const String& filePath) + { + setImage(filePath); + setPadding({ 0, 0, 0, 0 }); + setTypeName("ogfx::gui::widgets::ImageLabel"); + disableChildren(); + disableBackground(); + disableBorder(); + setStylesheetCategoryName("image"); + setSize(64, 64); + validate(); + return *this; + } + + void ImageLabel::applyTheme(const ostd::Stylesheet& theme) + { + enableAnimated(getThemeValue(theme, "animated", m_animated)); + setAnimationData(getThemeValue(theme, "animation", m_animData)); + String filePath = getThemeValue(theme, "path", m_image.getFilePath()); + if (filePath != m_image.getFilePath()) + setImage(filePath); + setSize(getThemeValue(theme, "size", getSize())); + if (isAnimatedEnabled()) + { + m_anim.create(m_animData); + m_anim.setSpriteSheet(m_image); + } + } + + void ImageLabel::onDraw(ogfx::BasicRenderer2D& gfx) + { + if (isAnimatedEnabled()) + gfx.drawAnimation(m_anim, getGlobalPosition() + getPadding().topLeft(), getSize() - getPadding().bottomRight()); + else + gfx.drawImage(m_image, getGlobalPosition() + getPadding().topLeft(), getSize() - getPadding().bottomRight()); + } + + void ImageLabel::onUpdate(void) + { + if (isAnimatedEnabled()) + m_anim.update(); + } + + void ImageLabel::setImage(const String& filePath) + { + if (filePath == "") return; + if (!ostd::FileSystem::fileExists(filePath)) + return; + m_image.destroy(); + m_image.loadFromFile(filePath, getWindow().getGFX()); + } + } } } diff --git a/src/ogfx/gui/widgets/Label.hpp b/src/ogfx/gui/widgets/Label.hpp index fb99cd7..0857e3a 100644 --- a/src/ogfx/gui/widgets/Label.hpp +++ b/src/ogfx/gui/widgets/Label.hpp @@ -21,6 +21,8 @@ #pragma once #include +#include +#include namespace ogfx { @@ -45,6 +47,26 @@ namespace ogfx String m_text { "" }; bool m_textChanged { false }; }; + class ImageLabel : public Widget + { + public: + inline ImageLabel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(""); } + inline ImageLabel(WindowCore& window, const String& text) : Widget({ 0, 0, 0, 0 }, window) { create(text); } + ImageLabel& create(const String& filePath); + void applyTheme(const ostd::Stylesheet& theme) override; + void onDraw(ogfx::BasicRenderer2D& gfx) override; + void onUpdate(void) override; + void setImage(const String& filePath); + inline Image& getImage(void) { return m_image; } + OSTD_BOOL_PARAM_GETSET_E(Animated, m_animated); + OSTD_PARAM_GETSET(AnimationData, AnimationData, m_animData); + + private: + Image m_image; + Animation m_anim; + AnimationData m_animData; + bool m_animated { false }; + }; } } } diff --git a/src/ogfx/gui/widgets/Scrollbar.cpp b/src/ogfx/gui/widgets/Scrollbar.cpp index 971c9aa..00b3282 100644 --- a/src/ogfx/gui/widgets/Scrollbar.cpp +++ b/src/ogfx/gui/widgets/Scrollbar.cpp @@ -323,7 +323,7 @@ namespace ogfx { if (isVScrollEnabled()) { - bool mouseInsideHScrollbar = m_hScrollbar.isMouseInsideThumb({ event.mouse->position_x, event.mouse->position_y }) && needsHScroll(); + bool mouseInsideHScrollbar = m_hScrollbar.isMouseInside() && needsHScroll(); if (std::abs(event.mouse->scrollAmount.y) > 0 && !mouseInsideHScrollbar) { m_scrollVelocity.y += m_scrollSpeed * event.mouse->scrollAmount.y * m_scrollSpeedMultiplier; diff --git a/src/ogfx/gui/widgets/Widget.cpp b/src/ogfx/gui/widgets/Widget.cpp index ef50a4b..3549ac7 100644 --- a/src/ogfx/gui/widgets/Widget.cpp +++ b/src/ogfx/gui/widgets/Widget.cpp @@ -244,7 +244,7 @@ namespace ogfx if (!isVisible()) return; beforeDraw(gfx); - if (m_useBackgroundGradient && m_showBorder) + if (m_useBackgroundGradient) gfx.fillGradientRect({ getGlobalPosition(), getSize() }, m_backgroundGradient); else if (m_showBackground) gfx.fillRoundRect({ getGlobalPosition(), getSize() }, m_backgroundColor, m_borderRadius); diff --git a/src/ogfx/render/BasicRenderer.cpp b/src/ogfx/render/BasicRenderer.cpp index 4829aa1..9f4d07d 100644 --- a/src/ogfx/render/BasicRenderer.cpp +++ b/src/ogfx/render/BasicRenderer.cpp @@ -218,7 +218,8 @@ namespace ogfx return set_error_state(tErrors::NoFont); if (m_font == nullptr) return set_error_state(tErrors::NullFont); - if (fontSize == m_fontSize || fontSize <= 0) return set_error_state(tErrors::NoError); + if (fontSize == m_fontSize || fontSize <= 0) + return set_error_state(tErrors::NoError); TTF_SetFontSize(m_font, fontSize); m_fontSize = fontSize; return set_error_state(tErrors::NoError); diff --git a/src/ogfx/resources/Image.cpp b/src/ogfx/resources/Image.cpp index 5f1cb0a..19a6905 100644 --- a/src/ogfx/resources/Image.cpp +++ b/src/ogfx/resources/Image.cpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #include "Image.hpp" @@ -25,19 +25,24 @@ namespace ogfx { - void Image::destroy(void) - { - SDL_DestroyTexture(m_sdl_texture); - m_loaded = false; - m_sdl_texture = nullptr; - m_width = 0; - m_height = 0; - } + void Image::destroy(void) + { + if (isValid() && isLoaded()) + SDL_DestroyTexture(m_sdl_texture); + m_loaded = false; + m_sdl_texture = nullptr; + m_width = 0; + m_height = 0; + m_filePath = ""; + invalidate(); + } - Image& Image::loadFromFile(const String& filePath, BasicRenderer2D& gfx) - { + Image& Image::loadFromFile(const String& filePath, BasicRenderer2D& gfx) + { + if (isLoaded() && isValid()) + return *this; if (!gfx.isInitialized()) - return *this; //TODO: Error + return *this; //TODO: Error m_sdl_texture = IMG_LoadTexture(gfx.getWindow().getSDLRenderer(), filePath.c_str()); if (!m_sdl_texture) { @@ -45,9 +50,10 @@ namespace ogfx return *this; } SDL_GetTextureSize(m_sdl_texture, &m_width, &m_height); + m_filePath = filePath; m_loaded = true; setTypeName("ogfx::Image"); validate(); return *this; - } + } } diff --git a/src/ogfx/resources/Image.hpp b/src/ogfx/resources/Image.hpp index a949370..39baefe 100644 --- a/src/ogfx/resources/Image.hpp +++ b/src/ogfx/resources/Image.hpp @@ -1,21 +1,21 @@ /* - OmniaFramework - A collection of useful functionality - Copyright (C) 2025 OmniaX-Dev + OmniaFramework - A collection of useful functionality + Copyright (C) 2025 OmniaX-Dev - This file is part of OmniaFramework. + This file is part of OmniaFramework. - OmniaFramework is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + OmniaFramework is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - OmniaFramework is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + OmniaFramework is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with OmniaFramework. If not, see . + You should have received a copy of the GNU General Public License + along with OmniaFramework. If not, see . */ #pragma once @@ -26,23 +26,25 @@ namespace ogfx { - class BasicRenderer2D; - class Image : public ostd::BaseObject - { - public: - inline Image(void) { invalidate(); } - inline Image(const String& filePath, BasicRenderer2D& gfx) { loadFromFile(filePath, gfx); } - inline ~Image(void) { destroy(); } - void destroy(void); - Image& loadFromFile(const String& filePath, BasicRenderer2D& gfx); - inline Vec2 getSize(void) const { return { m_width, m_height }; } - inline bool isLoaded(void) const { return m_loaded; } - inline SDL_Texture* getSDLTexture(void) const { return m_sdl_texture; } + class BasicRenderer2D; + class Image : public ostd::BaseObject + { + public: + inline Image(void) { invalidate(); } + inline Image(const String& filePath, BasicRenderer2D& gfx) { loadFromFile(filePath, gfx); } + inline ~Image(void) { destroy(); } + void destroy(void); + Image& loadFromFile(const String& filePath, BasicRenderer2D& gfx); + inline Vec2 getSize(void) const { return { m_width, m_height }; } + inline bool isLoaded(void) const { return m_loaded; } + inline SDL_Texture* getSDLTexture(void) const { return m_sdl_texture; } + inline String getFilePath(void) const { return m_filePath; } - private: - SDL_Texture* m_sdl_texture { nullptr }; - f32 m_width { 0 }; - f32 m_height { 0 }; - bool m_loaded { false }; - }; + private: + SDL_Texture* m_sdl_texture { nullptr }; + String m_filePath { "" }; + f32 m_width { 0 }; + f32 m_height { 0 }; + bool m_loaded { false }; + }; } diff --git a/src/ostd/io/Stylesheet.cpp b/src/ostd/io/Stylesheet.cpp index 69d64ec..8b43b9d 100644 --- a/src/ostd/io/Stylesheet.cpp +++ b/src/ostd/io/Stylesheet.cpp @@ -253,7 +253,7 @@ namespace ostd return false; String key = line.new_substr(0, line.indexOf("=")).trim(); String valuePreserveCase = line.new_substr(line.indexOf("=") + 1).trim(); - String value = line.new_substr(line.indexOf("=") + 1).trim().toLower(); + String value = valuePreserveCase.new_toLower(); if (key == "") return false; String themeID = ""; @@ -286,7 +286,7 @@ namespace ostd }; auto l_isFile = [this](String& value) -> bool { value.trim(); - if (value.startsWith("file(") && value.endsWith(")")) + if (value.new_toLower().startsWith("file(") && value.endsWith(")")) { value.substr(5, value.len() - 1).trim(); if (value.startsWith("\"") && value.endsWith("\"")) @@ -299,7 +299,7 @@ namespace ostd }; auto l_isAnim = [this](String& value) -> bool { value.trim(); - if (value.startsWith("anim(") && value.endsWith(")")) + if (value.new_toLower().startsWith("anim(") && value.endsWith(")")) { value.substr(5, value.len() - 1).trim(); return true; @@ -331,25 +331,25 @@ namespace ostd } else if (l_isColorGradientValue(value)) { - ColorGradient grad = parseColorGradient(value); + ColorGradient grad = parseColorGradient(valuePreserveCase, variables); if (grad.isInvalid()) return false; set(key, grad, themeID); } - else if (l_isAnim(value)) + else if (l_isAnim(valuePreserveCase)) { bool outError = false; - AnimationData ad = parseAnim(value, outError); + AnimationData ad = parseAnim(valuePreserveCase, outError, variables); if (outError) return false; set(key, ad, themeID); } - else if (l_isFile(value)) + else if (l_isFile(valuePreserveCase)) { - bool exists = ostd::FileSystem::fileExists(value) || - ostd::FileSystem::fileExists("./" + value); + bool exists = ostd::FileSystem::fileExists(valuePreserveCase) || + ostd::FileSystem::fileExists("./" + valuePreserveCase); if (exists) - set(key, value, themeID); + set(key, valuePreserveCase, themeID); else return false; } @@ -392,20 +392,7 @@ namespace ostd { if (exitCondition) return false; - String lineCopy = line; - std::vector>> sortedVars(variables.begin(), variables.end()); - std::sort(sortedVars.begin(), sortedVars.end(), [](const auto& a, const auto& b) { - return a.first.len() > b.first.len(); - }); - for (const auto&[var, val] : sortedVars) - { - if (lineCopy.contains(var)) - { - lineCopy.replaceAll(var, val.first); - break; - } - } - return parseThemeFileLine(lineCopy, variables, true); + return parseThemeFileLine(replaceVariables(line, variables), variables, true); } return true; } @@ -477,13 +464,13 @@ namespace ostd return newLines; } - ColorGradient Stylesheet::parseColorGradient(const String& _value) + ColorGradient Stylesheet::parseColorGradient(const String& _value, const VariableList& variables) { - String value = _value.new_toLower().trim(); + String value = _value.new_trim(); ColorGradient grad; f32 angle = 0.0f; bool weighted = false; - String gradientFunc = value.new_substr(0, value.indexOf("(")).trim(); + String gradientFunc = value.new_substr(0, value.indexOf("(")).trim().toLower(); String gradientVal = value.substr(value.indexOf("(") + 1, value.lastIndexOf(")")).trim(); if (gradientVal == "" || !gradientVal.contains("-")) @@ -511,6 +498,9 @@ namespace ostd i32 index = 0; for (auto& token : tokens) { + token = replaceVariables(token, variables); + if (token.new_toLower().startsWith("color(") && token.new_toLower().endsWith(")")) + token.substr(6, token.len() - 1).trim(); grad.addColor(Color(token)); if (index > 0) grad.addWeight(1.0f); @@ -525,10 +515,14 @@ namespace ostd { if (is_color) { + token = replaceVariables(token, variables); + if (token.new_toLower().startsWith("color(") && token.new_toLower().endsWith(")")) + token.substr(6, token.len() - 1).trim(); grad.addColor(Color(token)); } else { + token = replaceVariables(token, variables); if (!token.isNumeric(true)) return ColorGradient(); grad.addWeight(token.toFloat()); @@ -541,9 +535,9 @@ namespace ostd return grad; } - AnimationData Stylesheet::parseAnim(const String& _value, bool& outError) + AnimationData Stylesheet::parseAnim(const String& _value, bool& outError, const VariableList& variables) { - String value = _value.new_toLower().trim(); + String value = _value.new_trim(); AnimationData ad; auto tokens = value.tokenize(","); auto l_error = [&](bool err) -> AnimationData { @@ -554,8 +548,9 @@ namespace ostd { if (tok.count(":") != 1 || tok.startsWith(":") || tok.endsWith(":")) return l_error(true); - String prop = tok.new_substr(0, tok.indexOf(":")).trim(); + String prop = tok.new_substr(0, tok.indexOf(":")).trim().toLower(); String val = tok.new_substr(tok.indexOf(":") + 1).trim(); + val = replaceVariables(val, variables); if (prop == "framecount") { if (!val.isInt()) @@ -648,6 +643,25 @@ namespace ostd return l_error(false); } + String Stylesheet::replaceVariables(const String& line, const VariableList& variables, bool stop_at_first_match) + { + String lineCopy = line; + std::vector>> sortedVars(variables.begin(), variables.end()); + std::sort(sortedVars.begin(), sortedVars.end(), [](const auto& a, const auto& b) { + return a.first.len() > b.first.len(); + }); + for (const auto&[var, val] : sortedVars) + { + if (lineCopy.contains(var)) + { + lineCopy.replaceAll(var, val.first); + if (stop_at_first_match) + break; + } + } + return lineCopy; + } + void Stylesheet::debugPrint(void) { for (const auto&[key, value] : m_values) diff --git a/src/ostd/io/Stylesheet.hpp b/src/ostd/io/Stylesheet.hpp index a12442f..303caca 100644 --- a/src/ostd/io/Stylesheet.hpp +++ b/src/ostd/io/Stylesheet.hpp @@ -63,8 +63,9 @@ namespace ostd bool parseThemeFileLine(const String& line, const VariableList& variables, bool exitCondition = false); String parseGroupSelector(const String& rawSelector) const; stdvec parseGroup(const String& selector, const stdvec& group); - ColorGradient parseColorGradient(const String& _value); - AnimationData parseAnim(const String& _value, bool& outError); + ColorGradient parseColorGradient(const String& _value, const VariableList& variables); + AnimationData parseAnim(const String& _value, bool& outError, const VariableList& variables); + String replaceVariables(const String& line, const VariableList& variables, bool stop_at_first_match = true); private: stdumap m_values; diff --git a/src/ostd/math/Geometry.hpp b/src/ostd/math/Geometry.hpp index 6418b34..8d39148 100755 --- a/src/ostd/math/Geometry.hpp +++ b/src/ostd/math/Geometry.hpp @@ -369,13 +369,14 @@ namespace ostd inline virtual Vec2 topRight(void) const { return Vec2(getx() + getw(), gety()); } inline virtual Vec2 bottomLeft(void) const { return Vec2(getx(), gety() + geth()); } inline virtual Vec2 bottomRight(void) const { return Vec2(getx() + getw(), gety() + geth()); } + inline virtual Rectangle edgeRect(void) const { return { getx(), gety(), getx() + getw(), gety() + getw() }; } inline virtual f32 left(void) const { return getx(); } inline virtual f32 right(void) const { return getw(); } inline virtual f32 top(void) const { return gety(); } inline virtual f32 bottom(void) const { return geth(); } - inline String toString(void) const override { return String("{ ").add(x).add(", ").add(y).add(", ").add(w).add(", ").add(h).add(" }"); } + inline virtual String toString(void) const override { return String("{ ").add(x).add(", ").add(y).add(", ").add(w).add(", ").add(h).add(" }"); } inline virtual bool intersects(Rectangle rect, bool includeBounds = true) const { diff --git a/src/test/GuiTest.cpp b/src/test/GuiTest.cpp index 82c1356..9cd07e8 100644 --- a/src/test/GuiTest.cpp +++ b/src/test/GuiTest.cpp @@ -32,18 +32,6 @@ class Window : public ogfx::gui::Window inline Window(void) { } inline void onInitialize(void) override { - m_img.loadFromFile("./img.png", m_gfx); - ogfx::AnimationData ad; - ad.columns = 9; - ad.rows = 4; - ad.frameWidth = 256; - ad.frameHeight = 256; - ad.frameCount = 36; - ad.fps = 60; - m_anim.create(ad); - m_anim.setSpriteSheet(m_img); - - m_label1.setText("Show Panel2"); m_label1.setCallback(ogfx::gui::Widget::eCallback::MousePressed, [&](const ogfx::gui::Event& event) -> void { m_check1.setChecked(!m_check1.isChecked()); @@ -100,6 +88,7 @@ class Window : public ogfx::gui::Window m_panel2.addWidget(m_panel1, { 400, 50 }); m_panel2.addWidget(m_label1, { 0, 500 }); m_panel2.addWidget(m_btn1, { 0, 300 }); + m_panel2.addWidget(m_img, { 20, 150 }); addWidget(m_check1, { 30, 30 }); addWidget(m_panel2, { 500, 100 }); @@ -120,14 +109,10 @@ class Window : public ogfx::gui::Window void onRedraw(ogfx::BasicRenderer2D& gfx) override { - gfx.drawAnimation(m_anim, { 200, 200 }); - // std::cout << (i32)gfx.getDrawCallCount() << "\n"; - // gfx.fillRect(m_panel2.getGlobalPureContentBounds(), { 0, 255, 0, 120 }); } void onFixedUpdate(void) override { - m_anim.update(); } private: @@ -141,10 +126,9 @@ class Window : public ogfx::gui::Window Panel m_panel3 { *this }; CheckBox m_check1 { *this }; Button m_btn1 { *this }; + ImageLabel m_img { *this }; ostd::Stylesheet m_theme; - ogfx::Animation m_anim; - ogfx::Image m_img; }; i32 main(i32 argc, char** argv)