Skip to content

Commit

Permalink
[SUTK] Draw Order Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ravi688 committed Dec 29, 2024
1 parent 77cfaa5 commit 64298f6
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 11 deletions.
2 changes: 1 addition & 1 deletion shared-dependencies/BufferLib
Submodule BufferLib updated 1 files
+75 −0 source/buffer_test.c
8 changes: 5 additions & 3 deletions sutk/include/sutk/UIDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ namespace SUTK
com::Bool m_isCalledFirstTime;
std::chrono::time_point<std::chrono::steady_clock> m_prevTime;
f32 m_deltaTime;
// Caches the draw order range calculated in the last draw order recalculation
// This value is used to determine if new draw order range is different from the last calculated one
u32 m_drawOrderRange { U32_MAX };

// These two values hold max and min draw order values used in previou frame,
// and are used to determine if we need to recalcualte normalized draw order (depth values) for each Renderable in the next frame (current)
u32 m_maxDrawOrder { U32_MAX };
u32 m_minDrawOrder { U32_MAX };

// It should be set com::True if the current frame needs to be drawn
// Generally, it should remain set to com::False unless some UI component/widget has been marked as dirty or updated its appearance
Expand Down
39 changes: 39 additions & 0 deletions sutk/include/sutk/tests/DrawOrderTest.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <sutk/ITest.hpp>

#include <sge-cpp/sge.hpp>

#include <sutk/UIDriver.hpp>

namespace SUTK
{
class IGfxDriver;
class Button;
class Panel;

class DrawOrderTest : public ITest
{
private:
UIDriver* m_uiDriver;
IGfxDriver* m_gfxDriver;
IInputDriver* m_inputDriver { };
FullWindowContainer* m_rootContainer { };
Panel* m_panel1 { };
Panel* m_panel2 { };
Panel* m_panel;

public:
DrawOrderTest() : m_uiDriver(NULL), m_gfxDriver(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;
};
}
25 changes: 18 additions & 7 deletions sutk/source/UIDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ namespace SUTK
m_runnables.traverse(IRunnable::Update);

com::Bool isRerender = m_isRenderThisFrame;
bool isRecalculateDrawOrder = false;
com::Bool isRecalculateDrawOrder = com::False;
u32 minDrawOrder = std::numeric_limits<u32>::max();
u32 maxDrawOrder = 0;
// update GPU side data
Expand All @@ -102,8 +102,8 @@ namespace SUTK
}
if(renderable->isDirty())
renderable->update();
if(renderable->isDrawOrderDirty())
isRecalculateDrawOrder = true;
if(!isRecalculateDrawOrder && renderable->isDrawOrderDirty())
isRecalculateDrawOrder = com::True;
u32 drawOrder = renderable->getDrawOrder();
if(drawOrder < minDrawOrder)
minDrawOrder = drawOrder;
Expand All @@ -114,19 +114,30 @@ namespace SUTK
if(isRecalculateDrawOrder)
{
_com_assert(minDrawOrder <= maxDrawOrder);
// Proof:
//
// let x1 = minDrawOrder
// let x2 = maxDrawOrder
//
// k - (x1 + lambda1) k - x1
// ---------------------------- != -----------
// x2 - x2 + (lambda2- lambda1) x2 - x1
//
// Both the sides will be equal only when lambda1 and lambda2 are both zero
com::Bool isDrawOrderRangeChanged { (m_maxDrawOrder != maxDrawOrder) || (m_minDrawOrder != minDrawOrder) };
u32 drawOrderRange = maxDrawOrder - minDrawOrder;
com::Bool isDrawOrderRangeChanged { m_drawOrderRange != drawOrderRange };
f32 normalizeFactor = 1.0f / static_cast<f32>(m_drawOrderRange);
f32 normalizeFactor = 1.0f / static_cast<f32>(drawOrderRange);
for(auto it = m_renderables.begin(); it != m_renderables.end(); it++)
{
Renderable* renderable = (*it);
if(isDrawOrderRangeChanged || renderable->isDrawOrderDirty())
{
auto normDrawOrder = m_drawOrderRange ? ((1.0f - static_cast<f32>(renderable->getDrawOrder() - minDrawOrder) * normalizeFactor) * 99.0f) : 0;
auto normDrawOrder = drawOrderRange ? ((1.0f - static_cast<f32>(renderable->getDrawOrder() - minDrawOrder) * normalizeFactor) * 99.0f) : 0;
renderable->updateNormalizedDrawOrder(normDrawOrder);
}
}
m_drawOrderRange = drawOrderRange;
m_maxDrawOrder = maxDrawOrder;
m_minDrawOrder = minDrawOrder;
}

if(isRerender)
Expand Down
76 changes: 76 additions & 0 deletions sutk/source/tests/DrawOrderTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <sutk/tests/DrawOrderTest.hpp>

#include <sutk/SGEGfxDriver.hpp>
#include <sutk/SGEInputDriver.hpp>
#include <sutk/FullWindowContainer.hpp>

#include <sutk/Button.hpp>
#include <sutk/ButtonGraphic.hpp>
#include <sutk/Label.hpp>
#include <sutk/Panel.hpp>

namespace SUTK
{
ITest::TestInitializationData DrawOrderTest::getInitializationData()
{
auto data = ITest::getInitializationData();
data.driverInitializationData.title = "Draw Order Test";
return data;
}

void DrawOrderTest::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<FullWindowContainer>(com::null_pointer<Container>());
m_panel1 = m_uiDriver->createContainer<Panel>(rootContainer);
m_panel1->setRect({ 5, 5, 3, 1 });
m_panel1->setColor(Color4::blue());

m_panel2 = m_uiDriver->createContainer<Panel>(rootContainer);
m_panel2->setRect({ 5, 6.1f, 3, 1 });
m_panel2->setColor(Color4::yellow());

m_panel = m_uiDriver->createContainer<Panel>(rootContainer);
m_panel->setColor(Color4::green());
m_panel->setRect({ 4, 4, 10, 10 });
// EXPECT: This Panel must drawn on top of the Pane1 and Panel2 (previous two)
m_panel->setLayer(m_panel1->getMaxChildDistance() + m_panel1->getDepth() + 1);


m_inputDriver->getOnKeyEvent().subscribe([this](IInputDriver*, KeyCode key, KeyEvent action, ModifierKeys modifiers)
{
static com::Bool isSwap = com::True;
if(action == KeyEvent::Press)
{
if(isSwap)
m_panel->setLayer(0);
else
m_panel->setLayer(m_panel1->getMaxChildDistance() + m_panel1->getDepth() + 1);
isSwap = !isSwap;
std::cout << "Changing layer of m_panel" << std::endl;
}
});
}

void DrawOrderTest::terminate(SGE::Driver& driver)
{
m_uiDriver->destroyContainer<Panel>(m_panel2);
m_uiDriver->destroyContainer<Panel>(m_panel1);
m_uiDriver->destroyContainer<Panel>(m_panel);
m_uiDriver->destroyContainer<FullWindowContainer>(m_rootContainer);
delete m_uiDriver;
delete m_gfxDriver;
}

void DrawOrderTest::render(SGE::Driver& driver)
{
if(m_uiDriver->isDirty())
m_uiDriver->render();
}

void DrawOrderTest::update(SGE::Driver& driver, float deltaTime)
{
}
}
3 changes: 3 additions & 0 deletions sutk/source/tests/auto_tests/test.Container.getChildDepth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ namespace SUTK::AutoTests
EXPECT_EQ(cnt5->getMaxChildDistance(), 1);
EXPECT_EQ(cnt6->getMaxChildDistance(), 0);

cnt2->setLayer(0);
EXPECT_EQ(cnt2->getDepth(), 0);

driver->destroyContainer(cnt7);
driver->destroyContainer(cnt6);
driver->destroyContainer(cnt5);
Expand Down
20 changes: 20 additions & 0 deletions sutk/source/tests/auto_tests/test.Renderable.getDrawOrder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,35 @@ namespace SUTK::AutoTests

DummyRenderable* r4 = driver->createRenderable<DummyRenderable>(c4);
EXPECT_EQ(r4->getDrawOrder(), 2);
EXPECT_EQ(r4->isDrawOrderDirty(), true);
DummyRenderable* r5 = driver->createRenderable<DummyRenderable>(c5);
EXPECT_EQ(r5->getDrawOrder(), 2);
EXPECT_EQ(r5->isDrawOrderDirty(), true);
DummyRenderable* r8 = driver->createRenderable<DummyRenderable>(c8);
EXPECT_EQ(r8->getDrawOrder(), 4);
EXPECT_EQ(r8->isDrawOrderDirty(), true);
DummyRenderable* r9 = driver->createRenderable<DummyRenderable>(c9);
EXPECT_EQ(r9->getDrawOrder(), 5);
EXPECT_EQ(r9->isDrawOrderDirty(), true);
DummyRenderable* r10 = driver->createRenderable<DummyRenderable>(c10);
EXPECT_EQ(r10->getDrawOrder(), 5);
EXPECT_EQ(r10->isDrawOrderDirty(), true);

EXPECT_EQ(r4->getDrawOrder(), 2);
EXPECT_EQ(r5->getDrawOrder(), 2);
EXPECT_EQ(r8->getDrawOrder(), 4);
EXPECT_EQ(r9->getDrawOrder(), 5);
EXPECT_EQ(r10->getDrawOrder(), 5);

// Calls updateNormalizedDrawOrder()
driver->render();

EXPECT_EQ(r4->isDrawOrderDirty(), false);
EXPECT_EQ(r5->isDrawOrderDirty(), false);
EXPECT_EQ(r8->isDrawOrderDirty(), false);
EXPECT_EQ(r9->isDrawOrderDirty(), false);
EXPECT_EQ(r10->isDrawOrderDirty(), false);

c1->setLayer(1000);

EXPECT_EQ(r4->getDrawOrder(), 1002);
Expand All @@ -66,6 +80,12 @@ namespace SUTK::AutoTests
EXPECT_EQ(r9->getDrawOrder(), 1005);
EXPECT_EQ(r10->getDrawOrder(), 1005);

EXPECT_EQ(r4->isDrawOrderDirty(), true);
EXPECT_EQ(r5->isDrawOrderDirty(), true);
EXPECT_EQ(r8->isDrawOrderDirty(), true);
EXPECT_EQ(r9->isDrawOrderDirty(), true);
EXPECT_EQ(r10->isDrawOrderDirty(), true);

c2->setParent(com::null_pointer<Container>());

EXPECT_EQ(r4->getDrawOrder(), 1);
Expand Down

0 comments on commit 64298f6

Please sign in to comment.