Skip to content

Commit 537d678

Browse files
Implement scalable UI system and update map logic
Introduces a scalable UI system with anchor, pivot, and scaling support in GfxCanvas and GfxUIElement, including new layout and transform logic. Refactors map and chunk logic to use new MAP_CHUNK_SIZE and MAP_BLOCK_SPACING constants, adds composite block offset calculation, and updates block/model handling for improved flexibility. Adds new UI assets and updates test code to use the new UI system.
1 parent bb5bcc6 commit 537d678

22 files changed

+582
-124
lines changed

borealis.sln.DotSettings.user

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark9/@KeyIndexDefined">True</s:Boolean>
3+
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark9/Coords/@EntryValue">(Doc Ln 124 Col 22)</s:String>
4+
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark9/FileId/@EntryValue">96ECAD5E-82B9-086A-ABD2-F61197FE3DF8/d:src/d:brl/d:gfx/f:ui.cpp</s:String>
5+
<s:String x:Key="/Default/Housekeeping/Bookmarks/NumberedBookmarks/=Bookmark9/Owner/@EntryValue">NumberedBookmarkManager</s:String></wpf:ResourceDictionary>

include/borealis/ecs/entity.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ namespace brl
1212
glm::quat localRotation = glm::identity<glm::quat>();
1313
glm::vec3 localScale = glm::vec3(1.0);
1414

15-
glm::vec3 position();
15+
virtual glm::vec3 position();
1616
glm::quat rotation();
17-
glm::vec3 scale();
17+
virtual glm::vec3 scale();
1818
void lookAt(glm::vec3 point, glm::vec3 up = glm::vec3{0,1,0});
1919
void setEulerAngles(glm::vec3 euler);
2020

@@ -32,6 +32,10 @@ namespace brl
3232
template <typename T>
3333
T* getEntityInChildren();
3434

35+
36+
template <typename T>
37+
T* getEntity();
38+
3539
EcsEntity();
3640

3741
protected:
@@ -49,7 +53,7 @@ namespace brl
4953

5054
void internalDestroy();
5155

52-
glm::mat4 calculateTransform();
56+
virtual glm::mat4 calculateTransform();
5357

5458
std::vector<EcsEntity*> children;
5559
EcsEntity* parent = nullptr;
@@ -96,6 +100,12 @@ namespace brl
96100
return nullptr;
97101
}
98102

103+
template <typename T>
104+
T* EcsEntity::getEntity()
105+
{
106+
return dynamic_cast<T*>(this);
107+
}
108+
99109
struct EcsEngine {
100110

101111
EcsEngine();

include/borealis/gfx/engine.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace brl
5353
void shutdown();
5454
void update();
5555
bool isRunning() {return mainWindow->isOpen();}
56-
void insertCall(GfxMaterial* material, GfxAttribBuffer* buffer, const glm::mat4 transform, int instancingIdx = 0);
56+
void insertCall(GfxMaterial* material, GfxAttribBuffer* buffer, const glm::mat4& transform, int instancingIdx = 0);
5757
int getFrameCount();
5858

5959
float getAspectRatio();

include/borealis/gfx/ui.hpp

Lines changed: 118 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,29 @@ namespace brl
1414
{
1515

1616
EcsCamera* targetedCamera = nullptr;
17-
glm::vec2 scaledSize;
17+
18+
enum class ScaleMode
19+
{
20+
ConstantPixelSize,
21+
ScaleWithScreenSize,
22+
ConstantPhysicalSize
23+
};
24+
25+
ScaleMode mode = ScaleMode::ScaleWithScreenSize;
26+
27+
glm::vec2 referenceResolution;
28+
float referencePixelsPerUnit = 100.0f;
29+
float referenceDPI = 96.0f;
30+
31+
float matchWidthOrHeight = 0.5;
1832

1933
GfxCanvas();
2034
void earlyUpdate() override;
2135
void lateUpdate() override;
2236

2337
private:
2438
friend struct GfxImage;
39+
friend struct GfxUIElement;
2540
friend GfxEngine;
2641

2742
static GfxCanvas* mainCanvas;
@@ -32,22 +47,120 @@ namespace brl
3247

3348
void draw();
3449

50+
float GetScaleFactor(glm::vec2 screenResolution, float screenDPI = 96.0f)
51+
{
52+
switch (mode)
53+
{
54+
case ScaleMode::ConstantPixelSize:
55+
return 1.0f;
56+
57+
case ScaleMode::ScaleWithScreenSize:
58+
{
59+
float logWidth = std::log(screenResolution.x / referenceResolution.x);
60+
float logHeight = std::log(screenResolution.y / referenceResolution.y);
61+
float logScale = glm::mix(logWidth, logHeight, matchWidthOrHeight);
62+
return std::exp(logScale);
63+
}
64+
65+
case ScaleMode::ConstantPhysicalSize:
66+
return screenDPI / referenceDPI;
67+
}
68+
return 1.0f;
69+
}
70+
3571
std::vector<GfxUIDrawCall> draw_calls;
72+
73+
glm::vec2 ScaleUICoordinates(glm::vec2 uiPos, glm::vec2 screenResolution, float screenDPI = 96.0f)
74+
{
75+
float scale = GetScaleFactor(screenResolution, screenDPI);
76+
return uiPos * scale;
77+
}
78+
79+
glm::vec2 GetScaledCanvasSize(glm::vec2 screenResolution, float screenDPI = 96.0f)
80+
{
81+
float scale = GetScaleFactor(screenResolution, screenDPI);
82+
return screenResolution / scale; // Returns virtual resolution
83+
}
3684
};
3785

38-
struct GfxUIElement : EcsEntity
86+
struct GfxUIRect
3987
{
40-
GfxUIElement();
41-
void start() override;
88+
glm::vec2 position; // bottom-left corner
89+
glm::vec2 size;
90+
};
91+
4292

93+
struct GfxUIElement : EcsEntity
94+
{
95+
GfxUIElement(GfxCanvas* c);
96+
97+
// Anchor positions (0-1 range, relative to parent)
98+
glm::vec2 anchorMin = {0.5f, 0.5f}; // default: center
99+
glm::vec2 anchorMax = {0.5f, 0.5f}; // default: center
100+
101+
// Offsets in pixels from anchors
102+
glm::vec2 offsetMin = {-50, -50}; // left, bottom
103+
glm::vec2 offsetMax = {50, 50}; // right, top
104+
105+
// Pivot point (0-1 range, local to this element)
106+
glm::vec2 pivot = {0.5f, 0.5f}; // default: center
107+
108+
109+
GfxUIRect GetRect() const;
110+
111+
glm::mat4 calculateTransform() override;
112+
113+
void SetPosition(glm::vec2 pos)
114+
{
115+
if (anchorMin == anchorMax)
116+
{
117+
glm::vec2 size = GetSize();
118+
offsetMin = pos - size * pivot;
119+
offsetMax = offsetMin + size;
120+
}
121+
}
122+
123+
void SetSize(glm::vec2 size)
124+
{
125+
if (anchorMin == anchorMax)
126+
{
127+
glm::vec2 pos = GetPosition();
128+
offsetMin = pos - size * pivot;
129+
offsetMax = offsetMin + size;
130+
}
131+
}
132+
133+
glm::vec2 GetPosition() const
134+
{
135+
GfxUIRect rect = GetRect();
136+
return rect.position + rect.size * pivot;
137+
}
138+
139+
glm::vec2 GetSize() const { return GetRect().size; }
140+
141+
glm::vec2 GetWorldPosition() const
142+
{
143+
glm::vec2 localPos = GetPosition();
144+
if (parent && parent->getEntity<GfxUIElement>())
145+
{
146+
GfxUIRect parentRect = parent->getEntity<GfxUIElement>()->GetRect();
147+
return parentRect.position + localPos;
148+
}
149+
return localPos;
150+
}
43151

44152
protected:
45153
GfxCanvas* canvas;
154+
155+
46156
};
47157

48158
struct GfxImage : GfxUIElement
49159
{
50-
GfxTexture2d* texture;
160+
GfxImage(GfxCanvas* c);
161+
162+
glm::vec3 color = glm::vec3(1.0);
163+
GfxTexture2d* texture = GfxTexture2d::getWhiteTexture();
51164
GfxMaterial* material = new GfxMaterial(new GfxShaderProgram(brl::readFileString("D:/shaders/defaultui.glsl")));
52165

53166
void lateUpdate() override;

src/brl/gfx/engine.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <thread>
22

3+
#include "stb_image.h"
34
#include "borealis/gfx/ui.hpp"
45

56
#include "borealis/gfx/gfx.hpp"
@@ -109,6 +110,9 @@ void brl::GfxEngine::initialize()
109110
instance = this;
110111
materialMgr = new GfxMaterialMgr;
111112

113+
stbi_set_flip_vertically_on_load(true);
114+
115+
112116
auto vertexShaderSource = "#version 330 core\n"
113117
"layout (location = 0) in vec2 aPos;\n"
114118
"layout (location = 1) in vec2 aUV;\n"
@@ -254,7 +258,7 @@ void brl::GfxEngine::update()
254258

255259
}
256260

257-
void brl::GfxEngine::insertCall(GfxMaterial* material, GfxAttribBuffer* buffer, const glm::mat4 transform,
261+
void brl::GfxEngine::insertCall(GfxMaterial* material, GfxAttribBuffer* buffer, const glm::mat4& transform,
258262
int instancingIdx)
259263
{
260264
auto shader = material->getShader();

src/brl/gfx/texture.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ brl::GfxTexture2d::GfxTexture2d(std::string path)
3131

3232
IoFile file = readFileBinary(path);
3333

34-
stbi_set_flip_vertically_on_load(true);
3534

3635
unsigned char* data = stbi_load_from_memory(file.data, file.dataSize, &width, &height, &nrChannels, 4);
3736

src/brl/gfx/ui.cpp

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ brl::GfxCanvas::GfxCanvas()
99
if (!mainCanvas)
1010
mainCanvas = this;
1111

12-
scaledSize = glm::vec2
12+
referenceResolution = glm::vec2
1313
{
1414
GfxEngine::instance->getMainWidth(),
1515
GfxEngine::instance->getMainHeight(),
@@ -47,15 +47,12 @@ void brl::GfxCanvas::draw()
4747

4848
GfxShaderValue projValue{};
4949
GfxShaderValue timeValue{};
50-
float scale = 2.0f;
5150

52-
float aspect = scaledSize.x / scaledSize.y;
53-
float mainAspect = GfxEngine::instance->getAspectRatio();
51+
glm::vec2 screenSize = {GfxEngine::instance->getMainWidth(), GfxEngine::instance->getMainHeight()};
52+
// Apply to your UI projection matrix
53+
glm::vec2 virtualSize = GetScaledCanvasSize(screenSize);
5454

55-
scale = aspect / mainAspect;
56-
57-
projValue.m4value = glm::ortho(0.0f, static_cast<float>(GfxEngine::instance->getMainWidth()) / scale, 0.0f,
58-
static_cast<float>(GfxEngine::instance->getMainHeight()) / scale, -1.0f, 1.0f);
55+
projValue.m4value = glm::ortho(0.0f, virtualSize.x, virtualSize.y, 0.0f, -1.0f, 1.0f);
5956

6057
timeValue.floatValue = glfwGetTime();
6158

@@ -74,19 +71,75 @@ void brl::GfxCanvas::draw()
7471
}
7572
}
7673

77-
brl::GfxUIElement::GfxUIElement()
74+
brl::GfxUIElement::GfxUIElement(GfxCanvas* c)
75+
{
76+
canvas = c;
77+
}
78+
79+
brl::GfxUIRect brl::GfxUIElement::GetRect() const
80+
{
81+
auto parentSize = canvas->referenceResolution;
82+
83+
if (parent->getEntity<GfxUIElement>())
84+
parentSize = parent->getEntity<GfxUIElement>()->GetRect().size;
85+
86+
// Calculate anchor positions in pixels
87+
glm::vec2 anchorMinPixels = anchorMin * parentSize;
88+
glm::vec2 anchorMaxPixels = anchorMax * parentSize;
89+
90+
// Calculate corners
91+
glm::vec2 rectMin = anchorMinPixels + offsetMin;
92+
glm::vec2 rectMax = anchorMaxPixels + offsetMax;
93+
94+
// Size and position
95+
glm::vec2 size = rectMax - rectMin;
96+
glm::vec2 position = rectMin;
97+
98+
return {position, size};
99+
}
100+
101+
glm::mat4 brl::GfxUIElement::calculateTransform()
78102
{
103+
glm::vec2 screenSize = {GfxEngine::instance->getMainWidth(), GfxEngine::instance->getMainHeight()};
104+
105+
// Get scaled canvas size
106+
glm::vec2 canvasSize = canvas->GetScaledCanvasSize(screenSize);
107+
108+
// Set root parent size to canvas size
109+
if (!parent)
110+
{
111+
// This is a root element, use canvas size as parent
112+
}
113+
114+
// Get final position and size
115+
glm::vec2 position = GetWorldPosition();
116+
glm::vec2 size = GetSize();
117+
118+
// Apply scale factor
119+
float scaleFactor = canvas->GetScaleFactor(screenSize);
120+
position *= scaleFactor;
121+
size *= scaleFactor;
122+
123+
// Build transform matrix
124+
auto transform = glm::mat4(1.0f);
125+
transform = glm::translate(transform, glm::vec3(position, 0));
126+
transform = glm::scale(transform, glm::vec3(size, 1));
127+
128+
return transform;
79129
}
80130

81-
void brl::GfxUIElement::start()
131+
132+
brl::GfxImage::GfxImage(GfxCanvas* c) :
133+
GfxUIElement(c)
82134
{
83-
EcsEntity::start();
84-
canvas = getEntityInParent<GfxCanvas>();
85135
}
86136

87137
void brl::GfxImage::lateUpdate()
88138
{
89139
GfxUIElement::lateUpdate();
90140

141+
material->setTexture("_mainTexture", texture);
142+
material->setVec3("_mainColor", color);
143+
91144
canvas->insertDrawCall({calculateTransform(), GfxMesh::GetPrimitive(QUAD)->GetSubMesh(0)->buffer, material});
92145
}
-3.02 KB
Binary file not shown.
-3.49 KB
Binary file not shown.

0 commit comments

Comments
 (0)