From 6669ec7f4c3c5f40b29e20708d1ed4678635b8ed Mon Sep 17 00:00:00 2001 From: ravi688 Date: Tue, 31 Dec 2024 03:44:55 +0530 Subject: [PATCH] [SUTK] Fixed the root cause of incorrectly aligned Label's text; Added LABEL_TOGGLE_ACTIVE test - The cause of the bug was in SGE (Rendering backend) - Setting text data to text string didn't do anything if it was inactive, which resulted in incorrect values returned by IGfxDriver::getTextCoordFromGlyphIndex --- sutk/include/sutk/RenderRect.hpp | 3 +- sutk/include/sutk/RenderRectArray.hpp | 8 +- sutk/include/sutk/Renderable.hpp | 12 +-- sutk/include/sutk/SmallText.hpp | 34 +++++-- sutk/include/sutk/Text.hpp | 3 +- .../sutk/tests/LabelActiveToggleTest.hpp | 36 +++++++ sutk/source/ITest.cpp | 4 +- sutk/source/RenderRect.cpp | 24 +++-- sutk/source/RenderRectArray.cpp | 39 ++++---- sutk/source/Renderable.cpp | 7 +- sutk/source/SmallText.cpp | 99 +++++++------------ sutk/source/Text.cpp | 13 ++- sutk/source/UIDriver.cpp | 24 ++--- sutk/source/tests/LabelActiveToggleTest.cpp | 68 +++++++++++++ 14 files changed, 236 insertions(+), 138 deletions(-) create mode 100644 sutk/include/sutk/tests/LabelActiveToggleTest.hpp create mode 100644 sutk/source/tests/LabelActiveToggleTest.cpp diff --git a/sutk/include/sutk/RenderRect.hpp b/sutk/include/sutk/RenderRect.hpp index f398fc58..d5c35167 100644 --- a/sutk/include/sutk/RenderRect.hpp +++ b/sutk/include/sutk/RenderRect.hpp @@ -30,6 +30,7 @@ namespace SUTK virtual void onGlobalCoordDirty() noexcept override; virtual void onContainerResize(Rect2Df rect, bool isPositionChanged, bool isSizeChanged) noexcept override; virtual void updateNormalizedDrawOrder(f32 normalizedDrawOrder) noexcept override; + virtual void onActiveUpdate(com::Bool isActive) noexcept override; // Constructors RenderRect(UIDriver& driver, RenderableContainer* container, RenderMode renderMode = RenderMode::Opaque) noexcept; @@ -41,8 +42,6 @@ namespace SUTK virtual bool isDirty() noexcept override; virtual void update() noexcept override; - virtual void setActive(com::Bool isActive) noexcept override; - virtual Color4 getColor() const noexcept override { return m_color; } virtual void setColor(const Color4 color) noexcept override; }; diff --git a/sutk/include/sutk/RenderRectArray.hpp b/sutk/include/sutk/RenderRectArray.hpp index cbe19c69..cf699798 100644 --- a/sutk/include/sutk/RenderRectArray.hpp +++ b/sutk/include/sutk/RenderRectArray.hpp @@ -11,14 +11,15 @@ namespace SUTK private: Color4 m_color; bool m_isColorDirty; - bool m_isActiveDirty; std::vector m_rects; bool m_isRectsDirty; + protected: // overrides of Renderable::onGlobalCoordDirty(), and onContainerResize virtual void onGlobalCoordDirty() noexcept override; virtual void onContainerResize(Rect2Df rect, bool isPositionChanged, bool isSizeChanged) noexcept override; - + virtual void onActiveUpdate(com::Bool isActive) noexcept override; + virtual void updateNormalizedDrawOrder(f32 normalizedDrawOrder) noexcept override; public: // Constructors @@ -29,9 +30,6 @@ namespace SUTK virtual bool isDirty() override; virtual void update() override; - // Overrides of Renderable::setActive - virtual void setActive(com::Bool isActive) noexcept override; - const std::vector& getRects() const noexcept { return m_rects; } std::vector& getRectsForWrite() noexcept; diff --git a/sutk/include/sutk/Renderable.hpp b/sutk/include/sutk/Renderable.hpp index 7ca8866c..31390e12 100644 --- a/sutk/include/sutk/Renderable.hpp +++ b/sutk/include/sutk/Renderable.hpp @@ -23,10 +23,7 @@ namespace SUTK bool m_isDrawOrderDirty; // Initially it is set to false com::Bool m_isActiveDirty { }; - com::Bool m_isRedraw; - // Called by UIDriver to reset the redraw flag - void setRedraw(com::Bool isRedraw) noexcept { m_isRedraw = isRedraw; } // This must never be called outside of Renderable (at least for now) void setDrawOrder(u32 drawOrder) { m_drawOrder = drawOrder; m_isDrawOrderDirty = true; } @@ -46,13 +43,17 @@ namespace SUTK // updates draw order (z-buffer) values to the GPU side memory. // mandatory to be called in the overridng method virtual void updateNormalizedDrawOrder(f32 normalizedDrawOrder) { m_isDrawOrderDirty = false; } + // This function onActiveUpdate() is called inside Renderable::update() whenever isActiveDirty() returns true + // A deriving class can override this method to responde to activate and deactivate status changes. + // isActive: new value + virtual void onActiveUpdate(com::Bool isActive) noexcept { } public: Renderable(UIDriver& driver, RenderableContainer* container = NULL) noexcept; virtual ~Renderable() noexcept; // Override of Activatable::setActive() - virtual void setActive(com::Bool isActive) noexcept; + virtual void setActive(com::Bool isActive) noexcept override final; // returns true, if GPU side data is out of sync with respect to the CPU side data, otherwise false // Must be called in the overriding method @@ -73,9 +74,6 @@ namespace SUTK u32 getDrawOrder() const noexcept { return m_drawOrder; } - com::Bool isRedraw() const noexcept { return com::Bool { m_isRedraw || com::cast_away_const(this)->isDirty() || isDrawOrderDirty() }; } - void redraw() noexcept { m_isRedraw = com::True; } - bool ensureUpdated() noexcept { if(isDirty()) diff --git a/sutk/include/sutk/SmallText.hpp b/sutk/include/sutk/SmallText.hpp index 42bdf477..64eb285a 100644 --- a/sutk/include/sutk/SmallText.hpp +++ b/sutk/include/sutk/SmallText.hpp @@ -64,11 +64,31 @@ namespace SUTK class SUTK_API SmallText : public GfxDriverRenderable, public IColorable { private: - bool m_isPosDirty; - bool m_isDataDirty; - bool m_isPointSizeDirty; - bool m_isColorDirty; - bool m_isColorRangesDirty; + struct DirtyTable + { + bool isPosDirty; + bool isDataDirty; + bool isPointSizeDirty; + bool isColorDirty; + bool isColorRangesDirty; + void clear() noexcept + { + isPosDirty = false; + isDataDirty = false; + isPointSizeDirty = false; + isColorDirty = false; + isColorRangesDirty = false; + } + bool isAny() noexcept + { + return isPosDirty + || isDataDirty + || isPointSizeDirty + || isColorDirty + || isColorRangesDirty; + } + }; + DirtyTable m_dirtyTable {}; SmallTextData m_data; Color4 m_color; std::vector m_colorRanges; @@ -90,6 +110,7 @@ namespace SUTK virtual void onGlobalCoordDirty() noexcept override; virtual void onContainerResize(Rect2Df rect, bool isPositionChanged, bool isSizeChanged) noexcept override; virtual void updateNormalizedDrawOrder(f32 normalizedDrawOrder) override; + virtual void onActiveUpdate(com::Bool isActive) noexcept override; public: SmallText(UIDriver& driver, RenderableContainer* container, GfxDriverObjectHandleType textGroup, Color4 color = SUTK::Color4::white()) noexcept; @@ -103,9 +124,6 @@ namespace SUTK virtual void setColor(Color4 color) noexcept override; virtual Color4 getColor() const noexcept override; - // Override of Renderable::setActive() - virtual void setActive(com::Bool isActive) noexcept override; - void clearColorRanges() noexcept; void addColorRange(std::size_t pos, std::size_t len, const Color4 color) noexcept; diff --git a/sutk/include/sutk/Text.hpp b/sutk/include/sutk/Text.hpp index c8e4c9be..134db0f6 100644 --- a/sutk/include/sutk/Text.hpp +++ b/sutk/include/sutk/Text.hpp @@ -137,6 +137,7 @@ namespace SUTK virtual void onGlobalCoordDirty() noexcept override; virtual void onContainerResize(Rect2Df rect, bool isPositionChanged, bool isSizeChanged) noexcept override; virtual void updateNormalizedDrawOrder(f32 normalizedDrawOrder) override; + virtual void onActiveUpdate(com::Bool isActive) noexcept override; public: Vec2Df getLocalPositionFromCursorPosition(const CursorPosition& cursor) noexcept; @@ -152,8 +153,6 @@ namespace SUTK virtual bool isDirty() override; virtual void update() override; - virtual void setActive(com::Bool isActive) noexcept override; - void clear() noexcept; void setFont(UIDriver::FontReference font) noexcept; diff --git a/sutk/include/sutk/tests/LabelActiveToggleTest.hpp b/sutk/include/sutk/tests/LabelActiveToggleTest.hpp new file mode 100644 index 00000000..5d3c55cd --- /dev/null +++ b/sutk/include/sutk/tests/LabelActiveToggleTest.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include + +#include + +namespace SUTK +{ + class IGfxDriver; + class Label; + + class LabelActiveToggleTest : public ITest + { + private: + UIDriver* m_uiDriver; + IGfxDriver* m_gfxDriver; + IInputDriver* m_inputDriver; + FullWindowContainer* m_rootContainer { }; + Label* m_label { }; + + public: + LabelActiveToggleTest() : m_uiDriver(NULL), m_gfxDriver(NULL), m_inputDriver(NULL) { } + + TestInitializationData getInitializationData() override; + + void initialize(SGE::Driver& driver) override; + + void terminate(SGE::Driver& driver) override; + + void render(SGE::Driver& driver) override; + + void update(SGE::Driver& driver, float deltaTime) override; + }; +} diff --git a/sutk/source/ITest.cpp b/sutk/source/ITest.cpp index 5f428e0d..6fbd18c1 100644 --- a/sutk/source/ITest.cpp +++ b/sutk/source/ITest.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace SUTK { @@ -67,7 +68,8 @@ namespace SUTK { "PANEL", [] () { return std::unique_ptr(new PanelTest()); }}, { "LABEL", [] () { return std::unique_ptr(new LabelTest()); }}, { "PASSIVE_LABEL", [] () { return std::unique_ptr(new PassiveLabelTest()); }}, - { "DRAW_ORDER", [] () { return std::unique_ptr(new DrawOrderTest()); }} + { "DRAW_ORDER", [] () { return std::unique_ptr(new DrawOrderTest()); }}, + { "LABEL_ACTIVE_TOGGLE", [] () { return std::unique_ptr(new LabelActiveToggleTest()); }} }; std::unique_ptr ITest::Create(const std::string& testName) diff --git a/sutk/source/RenderRect.cpp b/sutk/source/RenderRect.cpp index 1a9d1dae..3600a2c3 100644 --- a/sutk/source/RenderRect.cpp +++ b/sutk/source/RenderRect.cpp @@ -23,18 +23,6 @@ namespace SUTK getUIDriver().getGfxDriver().destroyGeometry(getGfxDriverObjectHandle()); } - void RenderRect::setActive(com::Bool isActive) noexcept - { - // mandatory to call - GeometryRenderable::setActive(isActive); - // Activation and Deactivation Updates must happen immediately - if(auto handle = getGfxDriverObjectHandle(); handle != GFX_DRIVER_OBJECT_NULL_HANDLE) - { - GfxDriverObjectHandleType obj = getGfxDriver().getGeometryObject(handle); - getGfxDriver().setObjectActive(obj, isActive); - } - } - bool RenderRect::isDirty() noexcept { return GeometryRenderable::isDirty() || isRectDirty() || m_isColorDirty || m_isGeometryDirty; @@ -71,7 +59,7 @@ namespace SUTK void RenderRect::updateNormalizedDrawOrder(f32 normalizedDrawOrder) noexcept { // mandatory to be called in the overriding function - Renderable::updateNormalizedDrawOrder(normalizedDrawOrder); + GeometryRenderable::updateNormalizedDrawOrder(normalizedDrawOrder); GfxDriverObjectHandleType handle = getGfxDriverObjectHandle(); _com_assert(handle != GFX_DRIVER_OBJECT_NULL_HANDLE); @@ -79,6 +67,16 @@ namespace SUTK getGfxDriver().setObjectDepth(handle, normalizedDrawOrder); } + void RenderRect::onActiveUpdate(com::Bool isActive) noexcept + { + // Activation and Deactivation Updates must happen immediately + if(auto handle = getGfxDriverObjectHandle(); handle != GFX_DRIVER_OBJECT_NULL_HANDLE) + { + GfxDriverObjectHandleType obj = getGfxDriver().getGeometryObject(handle); + getGfxDriver().setObjectActive(obj, isActive); + } + } + void RenderRect::setColor(Color4 color) noexcept { m_color = color; diff --git a/sutk/source/RenderRectArray.cpp b/sutk/source/RenderRectArray.cpp index fefda8b9..b178009f 100644 --- a/sutk/source/RenderRectArray.cpp +++ b/sutk/source/RenderRectArray.cpp @@ -7,7 +7,6 @@ namespace SUTK RenderRectFillArray::RenderRectFillArray(UIDriver& driver, RenderableContainer* container, RenderMode renderMode) noexcept : GeometryRenderable(driver, container, renderMode), m_color(Color4::white()), m_isColorDirty(true), - m_isActiveDirty(false), m_isRectsDirty(false) { _com_assert(container != NULL); @@ -36,22 +35,13 @@ namespace SUTK bool RenderRectFillArray::isDirty() { - return GeometryRenderable::isDirty() || m_isRectsDirty || m_isColorDirty || m_isActiveDirty; + return GeometryRenderable::isDirty() || m_isRectsDirty || m_isColorDirty; } void RenderRectFillArray::update() { // Mandatory to be called in the overriding method GeometryRenderable::update(); - if(m_isActiveDirty) - { - auto handle = getGfxDriverObjectHandle(); - _com_assert(handle != GFX_DRIVER_OBJECT_NULL_HANDLE); - auto obj = getGfxDriver().getGeometryObject(handle); - getGfxDriver().setObjectActive(obj, isActive()); - m_isActiveDirty = false; - } - if(m_isRectsDirty) { Geometry::InstanceTransformArray& transformArray = getGeometry().getInstanceTransformArrayForWrite(); @@ -62,7 +52,6 @@ namespace SUTK transformArray.push_back(_rect); } } - if(m_isColorDirty) { getGeometry().fillColor(getColor()); @@ -78,13 +67,6 @@ namespace SUTK } } - void RenderRectFillArray::setActive(com::Bool isActive) noexcept - { - // mandatory to call - GeometryRenderable::setActive(isActive); - m_isActiveDirty = true; - } - std::vector& RenderRectFillArray::getRectsForWrite() noexcept { m_isRectsDirty = true; @@ -106,4 +88,23 @@ namespace SUTK { m_isRectsDirty = true; } + + void RenderRectFillArray::updateNormalizedDrawOrder(f32 normalizedDrawOrder) noexcept + { + // mandatory to be called in the overriding function + GeometryRenderable::updateNormalizedDrawOrder(normalizedDrawOrder); + + GfxDriverObjectHandleType handle = getGfxDriverObjectHandle(); + _com_assert(handle != GFX_DRIVER_OBJECT_NULL_HANDLE); + handle = getGfxDriver().getGeometryObject(handle); + getGfxDriver().setObjectDepth(handle, normalizedDrawOrder); + } + + void RenderRectFillArray::onActiveUpdate(com::Bool isActive) noexcept + { + auto handle = getGfxDriverObjectHandle(); + _com_assert(handle != GFX_DRIVER_OBJECT_NULL_HANDLE); + auto obj = getGfxDriver().getGeometryObject(handle); + getGfxDriver().setObjectActive(obj, isActive); + } } \ No newline at end of file diff --git a/sutk/source/Renderable.cpp b/sutk/source/Renderable.cpp index 37326d42..c4d168b3 100644 --- a/sutk/source/Renderable.cpp +++ b/sutk/source/Renderable.cpp @@ -4,7 +4,7 @@ namespace SUTK { - Renderable::Renderable(UIDriver& driver, RenderableContainer* container) noexcept : UIDriverObject(driver), m_container(container), m_drawOrder(0), m_isDrawOrderDirty(true), m_isRedraw(com::False) + Renderable::Renderable(UIDriver& driver, RenderableContainer* container) noexcept : UIDriverObject(driver), m_container(container), m_drawOrder(0), m_isDrawOrderDirty(true) { if(container != NULL) { @@ -38,15 +38,18 @@ namespace SUTK if(Activatable::isActive() != isActive) m_isActiveDirty = com::True; Activatable::setActive(isActive); + m_isDrawOrderDirty = true; } bool Renderable::isDirty() { - return static_cast(m_isActiveDirty); + return static_cast(m_isActiveDirty) || isActiveDirty(); } void Renderable::update() { + if(m_isActiveDirty) + onActiveUpdate(isActive()); m_isActiveDirty = com::False; } diff --git a/sutk/source/SmallText.cpp b/sutk/source/SmallText.cpp index 91d4cf14..1e1d5f2f 100644 --- a/sutk/source/SmallText.cpp +++ b/sutk/source/SmallText.cpp @@ -9,18 +9,15 @@ namespace SUTK { SmallText::SmallText(UIDriver& driver, RenderableContainer* container, GfxDriverObjectHandleType textGroup, Color4 color) noexcept : - GfxDriverRenderable(driver, container), - m_isPosDirty(true), - m_isDataDirty(false), - m_isPointSizeDirty(false), - m_isColorDirty(true), - m_isColorRangesDirty(false), + GfxDriverRenderable(driver, container), m_color(color), m_horizontalAlignment(HorizontalAlignment::Invalid), m_verticalAlignment(VerticalAlignment::Invalid), m_normalizedDrawOrder(0) { + m_dirtyTable.isColorDirty = true; + m_dirtyTable.isPosDirty = true; _com_assert(textGroup != GFX_DRIVER_OBJECT_NULL_HANDLE); setGfxDriverObjectHandle(getGfxDriver().createText(textGroup)); getGfxDriver().setTextFont(getGfxDriverObjectHandle(), m_font.getHandle()); @@ -35,37 +32,29 @@ namespace SUTK bool SmallText::isDirty() { - return GfxDriverRenderable::isDirty() || m_isPosDirty || m_isDataDirty || m_isPointSizeDirty || m_isColorRangesDirty || m_isColorDirty; + return GfxDriverRenderable::isDirty() || m_dirtyTable.isAny(); } void SmallText::update() { // Mandatory to be called in the overriding method GfxDriverRenderable::update(); - + auto dirtyTable = m_dirtyTable; + m_dirtyTable.clear(); // NOTE: Order of function calls are important here // should be updated before any updates to character array // this is because calling setTextColor() sets internal variable to 'm_color' // and it uses that variable in subsequent calls to setTextData() - if(m_isColorDirty) - { + if(dirtyTable.isColorDirty) getGfxDriver().setTextColor(getGfxDriverObjectHandle(), m_color); - m_isColorDirty = false; - } - if(m_isPointSizeDirty) - { + if(dirtyTable.isPointSizeDirty) getGfxDriver().setTextPointSize(getGfxDriverObjectHandle(), m_pointSize); - m_isPointSizeDirty = false; - } - if(m_isDataDirty) - { + if(dirtyTable.isDataDirty) getGfxDriver().setTextData(getGfxDriverObjectHandle(), m_data); - m_isDataDirty = false; - } - if(m_isPosDirty) + if(dirtyTable.isPosDirty) { Vec2Df pos = m_pos; if(getContainer() != NULL) @@ -74,27 +63,28 @@ namespace SUTK pos = getContainer()->getLocalCoordsToScreenCoords(pos); } getGfxDriver().setTextPosition(getGfxDriverObjectHandle(), { pos.x, pos.y, 0.0f }); - m_isPosDirty = false; } // should be updated after character array has been updated with setTextData(). - if(m_isColorRangesDirty) - { + if(dirtyTable.isColorRangesDirty) getGfxDriver().setTextColorRanges(getGfxDriverObjectHandle(), m_colorRanges.data(), static_cast(m_colorRanges.size())); - m_isColorRangesDirty = false; - } } void SmallText::updateNormalizedDrawOrder(f32 normalizedDrawOrder) { // mandatory to be called in the overriding function - Renderable::updateNormalizedDrawOrder(normalizedDrawOrder); + GfxDriverRenderable::updateNormalizedDrawOrder(normalizedDrawOrder); getGfxDriver().setTextDepth(getGfxDriverObjectHandle(), normalizedDrawOrder); m_normalizedDrawOrder = normalizedDrawOrder; } + void SmallText::onActiveUpdate(com::Bool isActive) noexcept + { + // Activatation or Deactivation updates must happen immediately + getGfxDriver().setTextActive(getGfxDriverObjectHandle(), isActive); + } void SmallText::setColor(Color4 color) noexcept { m_color = color; - m_isColorDirty = true; + m_dirtyTable.isColorDirty = true; } Color4 SmallText::getColor() const noexcept @@ -102,30 +92,23 @@ namespace SUTK return m_color; } - void SmallText::setActive(com::Bool isActive) noexcept - { - // mandatory to be called - Renderable::setActive(isActive); - // Activatation or Deactivation updates must happen immediately - getGfxDriver().setTextActive(getGfxDriverObjectHandle(), isActive); - } void SmallText::clearColorRanges() noexcept { m_colorRanges.clear(); - m_isColorRangesDirty = true; + m_dirtyTable.isColorRangesDirty = true; } void SmallText::addColorRange(std::size_t pos, std::size_t len, const Color4 color) noexcept { if(len == std::string::npos) len = getColumnCount(); m_colorRanges.push_back(ColorRange { static_cast(pos), static_cast(pos + len), color }); - m_isColorRangesDirty = true; + m_dirtyTable.isColorRangesDirty = true; } LineCountType SmallText::getColPosFromCoord(f32 coord) noexcept { // Ensure GPU side data is updated so that we get correct output from getTextGlyphIndexFromCoord() // NOTE: Data (chars) and PointSize both affect the value returned by getTextGlyphIndexFromCoord() - if(m_isDataDirty || m_isPointSizeDirty) + if(isDirty()) update(); return getGfxDriver().getTextGlyphIndexFromCoord(getGfxDriverObjectHandle(), coord); } @@ -133,89 +116,83 @@ namespace SUTK { // Ensure GPU side data is updated so that we get correct output from getTextGlyphIndexFromCoord() // NOTE: Data (chars) and PointSize both affect the value returned by getTextGlyphIndexFromCoord() - if(m_isDataDirty || m_isPointSizeDirty) + if(isDirty()) update(); return getGfxDriver().getTextCoordFromGlyphIndex(getGfxDriverObjectHandle(), col); } void SmallText::setData(const std::string_view data) noexcept { m_data = std::string(data); - m_isDataDirty = true; + m_dirtyTable.isDataDirty = true; } void SmallText::append(const std::string& data) noexcept { if(data.empty()) return; m_data += data; - m_isDataDirty = true; + m_dirtyTable.isDataDirty = true; } void SmallText::removeRange(std::size_t pos, std::size_t len) noexcept { if(len == 0) return; m_data.removeRange(pos, len); - m_isDataDirty = true; + m_dirtyTable.isDataDirty = true; } void SmallText::insert(LineCountType col, const std::string& data) noexcept { if(data.empty()) return; m_data.insert(col, data); - m_isDataDirty = true; + m_dirtyTable.isDataDirty = true; } void SmallText::setPosition(Vec2Df pos) noexcept { m_pos = pos; - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } void SmallText::addPosition(Vec2Df pos) noexcept { m_pos += pos; - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } void SmallText::subPosition(Vec2Df pos) noexcept { m_pos -= pos; - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } void SmallText::clear() noexcept { m_data.clear(); - m_isDataDirty = true; - } - void SmallText::updatePointSize() noexcept - { - if(m_isPointSizeDirty) - { - getGfxDriver().setTextPointSize(getGfxDriverObjectHandle(), m_pointSize); - m_isPointSizeDirty = false; - } + m_dirtyTable.isDataDirty = true; } void SmallText::onGlobalCoordDirty() noexcept { _com_assert(getContainer() != NULL); - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } void SmallText::onContainerResize(Rect2Df rect, bool isPositionChanged, bool isSizeChanged) noexcept { if(isSizeChanged) - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } void SmallText::setFontSize(const f32 pointSize) noexcept { - m_isPointSizeDirty = true; + m_dirtyTable.isPointSizeDirty = true; m_pointSize = pointSize; } f32 SmallText::getFontSize() noexcept { - updatePointSize(); + if(isDirty()) update(); return getGfxDriver().getTextPointSize(getGfxDriverObjectHandle()); } void SmallText::setFont(UIDriver::FontReference font) noexcept { getGfxDriver().setTextFont(getGfxDriverObjectHandle(), font.getHandle()); m_font = font; - redraw(); + // Setting m_isDataDirty to true would cause isDirty() to return true in UIDriver's render method which will the entire frame again + // It needs to be noted that the data is not dirty, we just want the frame to be redrawn. + m_dirtyTable.isDataDirty = true; } f32 SmallText::getBaselineHeight() noexcept { @@ -287,6 +264,6 @@ namespace SUTK { m_horizontalAlignment = hAlign; m_verticalAlignment = vAlign; - m_isPosDirty = true; + m_dirtyTable.isPosDirty = true; } } \ No newline at end of file diff --git a/sutk/source/Text.cpp b/sutk/source/Text.cpp index 78b0b120..9f1a5202 100644 --- a/sutk/source/Text.cpp +++ b/sutk/source/Text.cpp @@ -78,6 +78,12 @@ namespace SUTK getGfxDriver().setTextGroupDepth(m_textGroup, normalizedDrawOrder); } + void Text::onActiveUpdate(com::Bool isActive) noexcept + { + for(LineText* &lineText : m_lines) + lineText->setActive(isActive); + } + LineCountType Text::getNumChars(const CursorPosition& position) noexcept { std::size_t count = 0; @@ -177,13 +183,6 @@ namespace SUTK return { maxWidth, height }; } - void Text::setActive(com::Bool isActive) noexcept - { - Renderable::setActive(isActive); - for(LineText* &lineText : m_lines) - lineText->setActive(isActive); - } - void Text::clear() noexcept { // clear existing data diff --git a/sutk/source/UIDriver.cpp b/sutk/source/UIDriver.cpp index 57d164ec..39df719a 100644 --- a/sutk/source/UIDriver.cpp +++ b/sutk/source/UIDriver.cpp @@ -95,18 +95,20 @@ namespace SUTK for(auto it = m_renderables.begin(); it != m_renderables.end(); it++) { Renderable* renderable = *it; - if(!isRerender && renderable->isActiveForThisFrame() && renderable->isRedraw()) + if(renderable->isActiveForThisFrame()) { - isRerender = com::True; - renderable->setRedraw(com::False); + // Only update Renderables which are active and dirty + if(renderable->isDirty()) + { + renderable->update(); + if(!isRerender) + isRerender = com::True; + } + // If at least one Renderable's draw order is dirty then normalized draw orders need to be re-calculated + // and passed to the GPU driver + if(!isRecalculateDrawOrder && renderable->isDrawOrderDirty()) + isRecalculateDrawOrder = com::True; } - // Only update Renderables which are active and dirty - if(renderable->isActiveForThisFrame() && renderable->isDirty()) - renderable->update(); - // If at least Renderable's draw order is dirty then normalized draw orders need to be re-calculated - // and passed to the GPU driver - if(!isRecalculateDrawOrder && renderable->isActiveForThisFrame() && renderable->isDrawOrderDirty()) - isRecalculateDrawOrder = com::True; // Keep track of minimum and maximum draw order values u32 drawOrder = renderable->getDrawOrder(); if(drawOrder < minDrawOrder) @@ -134,7 +136,7 @@ namespace SUTK for(auto it = m_renderables.begin(); it != m_renderables.end(); it++) { Renderable* renderable = (*it); - if(isDrawOrderRangeChanged || (renderable->isActiveForThisFrame() && renderable->isDrawOrderDirty())) + if(isDrawOrderRangeChanged || (renderable->isActive() && renderable->isDrawOrderDirty())) { auto normDrawOrder = drawOrderRange ? ((1.0f - static_cast(renderable->getDrawOrder() - minDrawOrder) * normalizeFactor) * 99.0f) : 0; renderable->updateNormalizedDrawOrder(normDrawOrder); diff --git a/sutk/source/tests/LabelActiveToggleTest.cpp b/sutk/source/tests/LabelActiveToggleTest.cpp new file mode 100644 index 00000000..4f1eafd5 --- /dev/null +++ b/sutk/source/tests/LabelActiveToggleTest.cpp @@ -0,0 +1,68 @@ +#include + +#include +#include +#include + +#include + +#include + +namespace SUTK +{ + ITest::TestInitializationData LabelActiveToggleTest::getInitializationData() + { + auto data = ITest::getInitializationData(); + data.driverInitializationData.title = "Label Active Toggle Test (press Any key to toggle Active state)"; + return data; + } + + void LabelActiveToggleTest::initialize(SGE::Driver& driver) + { + m_gfxDriver = new SGEGfxDriver(driver); + m_inputDriver = new SGEInputDriver(driver); + m_uiDriver = new UIDriver(*m_gfxDriver, *m_inputDriver); + FullWindowContainer* rootContainer = m_rootContainer = m_uiDriver->createContainer(com::null_pointer()); + m_label = m_uiDriver->createContainer