Compare commits

...

6 commits

Author SHA1 Message Date
IlyaShurupov
e2072d257f tmp 2024-05-03 15:09:26 +03:00
IlyaShurupov
86a41c1876 tmp 2024-04-29 12:37:39 +03:00
IlyaShurupov
8171ba03da tmp 2024-04-18 12:54:37 +03:00
IlyaShurupov
2160dfca34 tmp 2024-04-13 12:28:46 +03:00
IlyaShurupov
e161fffc0c tmp 2024-04-12 16:27:21 +03:00
IlyaShurupov
a9fbb909ac tmp 2024-04-12 15:27:40 +03:00
44 changed files with 1201 additions and 370 deletions

22
3DEditor/CMakeLists.txt Normal file
View file

@ -0,0 +1,22 @@
project(3DEditor)
### ---------------------- Externals --------------------- ###
set(BINDINGS_INCLUDE ../Externals/glfw/include ../Externals)
set(BINDINGS_LIBS glfw Imgui)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
target_link_libraries(${PROJECT_NAME} PUBLIC Graphics Connection Widgets Math RasterRender)
target_link_libraries(${PROJECT_NAME} PUBLIC ${BINDINGS_LIBS})
### -------------------------- Applications -------------------------- ###
add_executable(3DEditorApp ./applications/Entry.cpp ./applications/SceneLoad.cpp)
target_link_libraries(3DEditorApp ${PROJECT_NAME} Lua ImageIO)
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
file(COPY "rsc/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -0,0 +1,42 @@
#include "EditorWidget.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
bool loadMeshes(tp::Scene& scene, const std::string& objetsPath);
class EditorGUI : public Application {
public:
EditorGUI() {
Vec2F renderResolution = { 1000, 1000 };
auto canvas = this->mGraphics->getCanvas();
// mGui = new EditorWidget<EventHandler, Canvas>(canvas, &geometry, renderResolution);
mGui = new ShortcutsTest<EventHandler, Canvas>();
loadMeshes(geometry, "rsc/scene.obj");
geometry.mCamera.lookAtPoint({ 0, 0, 0 }, { 3, 3, 2 }, { 0, 0, 1 });
}
~EditorGUI() override { delete mGui; }
void processFrame(EventHandler* eventHandler) override {
auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui->proc(*eventHandler, rec, rec);
}
void drawFrame(Canvas* canvas) override { mGui->draw(*canvas); }
private:
Scene geometry;
ShortcutsTest<EventHandler, Canvas>* mGui;
};
int main() {
EditorGUI gui;
gui.run();
}

View file

@ -0,0 +1,41 @@
#include "Scene.hpp"
#include "obj/OBJ_Loader.h"
#include <filesystem>
bool loadMeshes(tp::Scene& scene, const std::string& objetsPath) {
using namespace tp;
objl::Loader Loader;
if (!Loader.LoadFile(objetsPath.c_str())) {
std::cout << "Failed to Load File. May have failed to find it or it was not an .obj file.\n";
return false;
}
for (auto& curMesh : Loader.LoadedMeshes) {
scene.mObjects.append(Object());
auto object = &scene.mObjects.last();
for (auto& vertex : curMesh.Vertices) {
// printf("{ %f, %f, %f }, \n", vertex.Position.X, vertex.Position.Y, vertex.Position.Z);
object->mTopology.Points.append(Vec3F{ vertex.Position.X, vertex.Position.Y, vertex.Position.Z });
object->mTopology.Normals.append(Vec3F{ vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z });
}
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
uint idx1 = (int) curMesh.Indices[j];
uint idx2 = (int) curMesh.Indices[j + 1];
uint idx3 = (int) curMesh.Indices[j + 2];
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
object->mTopology.Indexes.append({ idx1, idx2, idx3 });
}
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
printf("Logic error loading normals\n");
}
}
return scene.mObjects.size();
}

110
3DEditor/private/Render.cpp Normal file
View file

@ -0,0 +1,110 @@
#include "Render.hpp"
#include "GraphicsApi.hpp"
using namespace tp;
class ObjectBuffers {
public:
ObjectBuffers(Object* object) {
mObject = (object);
auto& buff = mObject->mTopology.Points;
auto& indices = mObject->mTopology.Indexes;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vec3F) * buff.size(), buff.getBuff(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Vec3<uhalni>) * indices.size(), indices.getBuff(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Object* mObject = nullptr;
GLuint VAO = 0;
GLuint VBO = 0;
GLuint EBO = 0;
void drawCall() {
auto& indices = mObject->mTopology.Indexes;
glBindVertexArray(VAO);
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, indices.size() * 3, GL_UNSIGNED_INT, nullptr);
// glDrawArrays(GL_TRIANGLES, 0, sizeof(buffer) / (2 * sizeof(float)));
// glBindVertexArray(0);
}
~ObjectBuffers() {
glDeleteBuffers(1, &VBO);
glDeleteVertexArrays(1, &VAO);
}
};
Render::Render(Vec2F renderResolution) :
mRenderBuffer(renderResolution) {
mDefaultShader.load("rsc/shaders/default.vert", nullptr, "rsc/shaders/default.frag", true);
}
Render::~Render() {}
uint4 Render::getRenderBuffer() { return mRenderBuffer.texId(); }
Vec2F Render::getBufferSize() { return mRenderBuffer.getSize(); }
void Render::render(const Scene& geometry, Vec2F size) {
for (auto object : geometry.mObjects) {
if (!object->mBuffers) {
object->mBuffers = std::make_shared<ObjectBuffers>(&object.data());
}
}
mRenderBuffer.mClearCol = { 0.0f, 0.0f, 0.0f, 0.f };
mRenderBuffer.beginDraw();
mRenderBuffer.clear();
mDefaultShader.bind();
Mat4F cameraMat = geometry.mCamera.calculateTransformationMatrix();
glEnable(GL_DEPTH_TEST);
for (auto object : geometry.mObjects) {
static auto origin = (GLint) mDefaultShader.getu("Origin");
static auto basis = (GLint) mDefaultShader.getu("Basis");
static auto camera = (GLint) mDefaultShader.getu("Camera");
Mat4F basisMat;
Vec4F originPoint;
glUniform4fv(origin, 1, &originPoint[0]);
glUniformMatrix4fv(basis, 1, false, &basisMat[0][0]);
glUniformMatrix4fv(camera, 1, true, &cameraMat[0][0]);
object->mBuffers->drawCall();
}
mDefaultShader.unbind();
mRenderBuffer.endDraw();
}

View file

@ -0,0 +1,104 @@
#include "Widgets.hpp"
#include "Render.hpp"
namespace tp {
template <typename Events, typename Canvas>
class ShortcutsTest : public Widget<Events, Canvas> {
public:
ShortcutsTest() { this->createConfig("ShortcutsTest"); }
void action(const Events&) {
//
}
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
this->mVisible = areaParent.isOverlap(aArea);
if (!this->mVisible) return;
}
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
canvas.rect(this->mArea, this->getColor("Base"));
}
void populateConfig() override {
this->addColor("Base", "Base");
this->addOperator("OperatorName", { this, [](void* self, const Events& events) {
((ShortcutsTest*) self)->action(events);
} });
this->getShortcuts("OperatorName").append({ { "Alt", "Hold" }, { "Mouse1", "Hold" } });
this->getShortcuts("OperatorName").append({ { "Alt", "Hold" }, { "Mouse1", "Hold" } });
}
};
template <typename Events, typename Canvas>
class ViewportWidget : public Widget<Events, Canvas> {
public:
explicit ViewportWidget(Canvas* canvas, Scene* geometry, Vec2F renderResolution) :
mRender(renderResolution) {
this->createConfig("ViewportWidget");
mImage = canvas->createImageFromTextId(mRender.getRenderBuffer(), mRender.getBufferSize());
mGeometry = geometry;
mCanvas = canvas;
}
~ViewportWidget() { mCanvas->deleteImageHandle(mImage); }
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
this->mVisible = areaParent.isOverlap(aArea);
if (!this->mVisible) return;
mGeometry->mCamera.rotate(0.01f, 0.0);
}
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
mRender.render(*mGeometry, this->mArea.size);
canvas.drawImage(this->mArea, &mImage, PI);
}
public:
Render mRender;
Scene* mGeometry = nullptr;
Canvas* mCanvas = nullptr;
Canvas::ImageHandle mImage;
};
template <typename Events, typename Canvas>
class EditorWidget : public Widget<Events, Canvas> {
public:
EditorWidget(Canvas* canvas, Scene* geometry, Vec2F renderResolution) :
mViewport(canvas, geometry, renderResolution) {
this->createConfig("EditorWidget");
this->addColor("Base", "Base");
}
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
this->mVisible = areaParent.isOverlap(aArea);
if (!this->mVisible) return;
mSplitView.proc(events, aArea, aArea);
mViewport.proc(events, aArea, mSplitView.getFirst());
}
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
canvas.rect(this->mArea, this->getColor("Base"));
mSplitView.draw(canvas);
mViewport.draw(canvas);
}
public:
ViewportWidget<Events, Canvas> mViewport;
SplitView<Events, Canvas> mSplitView;
};
}

View file

@ -0,0 +1,23 @@
#pragma once
#include "Scene.hpp"
#include "Rect.hpp"
#include "FrameBuffer.hpp"
#include "Shader.hpp"
namespace tp {
class Render {
public:
explicit Render(Vec2F renderResolution);
~Render();
void render(const Scene& geometry, Vec2F size);
uint4 getRenderBuffer();
Vec2F getBufferSize();
private:
RenderBuffer mRenderBuffer;
RenderShader mDefaultShader;
};
}

34
3DEditor/public/Scene.hpp Normal file
View file

@ -0,0 +1,34 @@
#pragma once
#include "Topology.hpp"
#include <memory>
class ObjectBuffers;
namespace tp {
class Object {
public:
Object() = default;
public:
Topology mTopology;
std::shared_ptr<ObjectBuffers> mBuffers;
};
struct PointLight {
Vec3F pos;
halnf fallOut = 1.f;
halnf intensity = 1.f;
};
class Scene {
public:
Scene() = default;
public:
Buffer<Object> mObjects;
Buffer<PointLight> mLights;
Camera mCamera;
};
}

BIN
3DEditor/rsc/Font.ttf Normal file

Binary file not shown.

112
3DEditor/rsc/scene.obj Normal file
View file

@ -0,0 +1,112 @@
# Blender v3.0.1 OBJ File: 'scene.blend'
# www.blender.org
mtllib meshes.mtl
o Cube
v -1.039076 1.039076 1.792917
v -1.039076 1.039076 -1.285234
v 1.039076 1.039076 1.792917
v 1.039076 1.039076 -1.285234
v -1.039076 -1.039076 1.792917
v -1.039076 -1.039076 -1.285234
v 1.039076 -1.039076 1.792917
v 1.039076 -1.039076 -1.285234
vt 0.625000 0.500000
vt 0.625000 0.750000
vt 0.875000 0.750000
vt 0.875000 0.500000
vt 0.375000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.375000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.625000 0.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.375000 0.500000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 0.0000
usemtl Material
s off
f 1/1/1 3/2/1 7/3/1 5/4/1
f 4/5/2 8/6/2 7/7/2 3/2/2
f 8/8/3 6/9/3 5/10/3 7/11/3
f 6/12/4 8/13/4 4/5/4 2/14/4
f 6/9/5 2/14/5 1/1/5 5/10/5
o Cube.001
v 0.411013 -0.208216 -1.264212
v 0.411013 -0.208216 -0.612621
v -0.208216 -0.411013 -1.264212
v -0.208216 -0.411013 -0.612621
v 0.208216 0.411013 -1.264212
v 0.208216 0.411013 -0.612621
v -0.411013 0.208216 -1.264212
v -0.411013 0.208216 -0.612621
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn 0.3112 -0.9503 0.0000
vn -0.9503 -0.3112 0.0000
vn -0.3112 0.9503 0.0000
vn 0.9503 0.3112 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl None
s off
f 9/15/6 10/16/6 12/17/6 11/18/6
f 11/18/7 12/17/7 16/19/7 15/20/7
f 15/20/8 16/19/8 14/21/8 13/22/8
f 13/22/9 14/21/9 10/23/9 9/24/9
f 11/25/10 15/20/10 13/22/10 9/26/10
f 16/19/11 12/27/11 10/28/11 14/21/11
o Cube.002
v -0.351718 -0.467100 -0.602050
v -0.351718 -0.467100 0.049542
v -0.800825 0.004996 -0.602050
v -0.800825 0.004996 0.049542
v 0.120377 -0.017993 -0.602050
v 0.120377 -0.017993 0.049542
v -0.328730 0.454103 -0.602050
v -0.328730 0.454103 0.049542
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn -0.7245 -0.6892 0.0000
vn -0.6892 0.7245 0.0000
vn 0.7245 0.6892 0.0000
vn 0.6892 -0.7245 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl None
s off
f 17/29/12 18/30/12 20/31/12 19/32/12
f 19/32/13 20/31/13 24/33/13 23/34/13
f 23/34/14 24/33/14 22/35/14 21/36/14
f 21/36/15 22/35/15 18/37/15 17/38/15
f 19/39/16 23/34/16 21/36/16 17/40/16
f 24/33/17 20/41/17 18/42/17 22/35/17

View file

@ -0,0 +1,7 @@
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(gl_FragCoord.z, gl_FragCoord.z, gl_FragCoord.z, 1.f);
}

View file

@ -0,0 +1,11 @@
#version 330 core
layout(location = 0) in vec3 Point;
uniform vec4 Origin;
uniform mat4 Basis;
uniform mat4 Camera;
void main() {
gl_Position = Camera * vec4(Point.xyz, 1.0);
}

View file

@ -22,4 +22,6 @@ add_subdirectory(DataAnalysis)
add_subdirectory(Objects)
add_subdirectory(Widgets)
add_subdirectory(LibraryViewer)
add_subdirectory(Sketch3D)
add_subdirectory(RasterRender)
add_subdirectory(Sketch3D)
add_subdirectory(3DEditor)

View file

@ -11,7 +11,12 @@ namespace tp {
return hash(key);
}
template <typename tKey, typename tVal, class tAllocator = DefaultAllocator, ualni (*tHashFunc)(SelectValueOrReference<tKey>) = DefaultHashFunc<tKey>, int tTableInitialSize = 4>
template <
typename tKey,
typename tVal,
class tAllocator = DefaultAllocator,
ualni (*tHashFunc)(SelectValueOrReference<tKey>) = DefaultHashFunc<tKey>,
int tTableInitialSize = 4>
class Map {
enum {
@ -223,6 +228,13 @@ namespace tp {
return mTable[slot]->val;
}
tVal& operator[](KeyArg key) {
auto idx = presents(key);
if (idx.isValid()) return getSlotVal(idx);
put(key, {});
return get(key);
}
tVal& getSlotVal(ualni slot) {
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
return mTable[slot]->val;
@ -242,7 +254,7 @@ namespace tp {
if (this == &in) {
return *this;
}
for (ualni i = 0; i < mNSlots; i++) {
if (mTable[i] && !isDeletedNode(mTable[i])) {
deleteNode(mTable[i]);

View file

@ -62,7 +62,7 @@ namespace tp {
ImageHandle createImageFromTextId(ualni id, Vec2F size);
void deleteImageHandle(ImageHandle image);
void drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding);
void drawImage(const RectF& rec, ImageHandle* image, halnf angle = 0, halnf alpha = 1.f, halnf rounding = 0.f);
private:
Buffer<RectF> mScissors;
@ -71,7 +71,9 @@ namespace tp {
class Graphics {
public:
explicit Graphics(Window* window) : mGui(window), mCanvas(window) {}
explicit Graphics(Window* window) :
mGui(window),
mCanvas(window) {}
void procBegin() {
mCanvas.procBegin();
@ -88,14 +90,12 @@ namespace tp {
mGui.drawBegin();
}
void drawEnd() {
void drawEnd() {
mCanvas.drawEnd();
mGui.drawEnd();
}
Canvas* getCanvas() {
return &mCanvas;
}
Canvas* getCanvas() { return &mCanvas; }
private:
Canvas mCanvas;

View file

@ -34,7 +34,7 @@ namespace tp {
Buffer<Vec3F> Points;
Buffer<Vec3F> Normals;
Buffer<Vec3I> Indexes;
Buffer<Vec3<uhalni>> Indexes;
};
struct TopologyCache {

View file

@ -6,9 +6,9 @@
using namespace tp;
using namespace obj;
class ExampleGUI : public Application {
class SimpleGUI : public Application {
public:
ExampleGUI() { gui.cd(objects_api::create<DictObject>(), "root"); }
SimpleGUI() { gui.cd(objects_api::create<DictObject>(), "root"); }
void processFrame(EventHandler* eventHandler) override {}
@ -28,7 +28,7 @@ int main() {
if (module.initialize()) {
{
ExampleGUI gui;
SimpleGUI gui;
gui.run();
}
module.deinitialize();

View file

@ -0,0 +1,15 @@
project(RasterRender)
### ---------------------- Externals --------------------- ###
set(BINDINGS_INCLUDE ${GLEW_INCLUDE_DIR})
set(BINDINGS_LIBS ${GLEW_LIB})
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Connection)
target_link_libraries(${PROJECT_NAME} PUBLIC ${BINDINGS_LIBS})

View file

@ -5,20 +5,26 @@
#include <stdio.h>
void glerr(GLenum type) { printf("GL ERROR\n"); }
#define AssertGL(x) { x; GLenum __gle = glGetError(); if (__gle != GL_NO_ERROR) glerr(__gle); }
#define AssertGL(x) \
{ \
x; \
GLenum __gle = glGetError(); \
if (__gle != GL_NO_ERROR) glerr(__gle); \
}
using namespace tp;
RenderBuffer::RenderBuffer(const Vec2F& size) :
mSize(size) {
mDrawBuffers[0] = {GL_COLOR_ATTACHMENT0};
mDrawBuffers[0] = { GL_COLOR_ATTACHMENT0 };
// --------- texture ---------
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
// Give an empty image to OpenGL ( the last "0" )
AssertGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
AssertGL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)
);
// Poor filtering. Needed
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
@ -26,7 +32,7 @@ RenderBuffer::RenderBuffer(const Vec2F& size) :
// --------- depth ---------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorage(GL_RENDERBUFFER, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
AssertGL(glRenderbufferStorage(GL_RENDERBUFFER, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei) size.x, (GLsizei) size.y));
// ------------ framebuffer ------------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
@ -49,18 +55,24 @@ RenderBuffer::RenderBuffer(const Vec2F& size, tp::uint1 samples) :
AssertGL(glGenTextures(1, &mTextureId));
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
#ifdef ENV_OS_ANDROID
AssertGL(glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
AssertGL(
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei) size.x, (GLsizei) size.y, GL_TRUE)
);
#else
AssertGL(glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei)size.x, (GLsizei)size.y, GL_TRUE));
AssertGL(
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, (GLsizei) size.x, (GLsizei) size.y, GL_TRUE)
);
#endif
// !?
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
// AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
// ------- depth -------
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, mDepthBufferID));
AssertGL(glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei)size.x, (GLsizei)size.y));
AssertGL(glRenderbufferStorageMultisample(
GL_RENDERBUFFER, samples, GLW_CONTEXT_DEPTH_COMPONENT, (GLsizei) size.x, (GLsizei) size.y
));
// ------- fbuff -------
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
@ -72,9 +84,7 @@ RenderBuffer::RenderBuffer(const Vec2F& size, tp::uint1 samples) :
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
uint4 RenderBuffer::buffId() const {
return mFrameBufferID;
}
uint4 RenderBuffer::buffId() const { return mFrameBufferID; }
void RenderBuffer::beginDraw() {
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
@ -82,7 +92,7 @@ void RenderBuffer::beginDraw() {
}
void RenderBuffer::setViewport(const RectF& viewport) {
AssertGL(glViewport((GLsizei)viewport.x, (GLsizei)viewport.y, (GLsizei)viewport.z, (GLsizei)viewport.w));
AssertGL(glViewport((GLsizei) viewport.x, (GLsizei) viewport.y, (GLsizei) viewport.z, (GLsizei) viewport.w));
}
void RenderBuffer::clear() {
@ -102,9 +112,6 @@ RenderBuffer::~RenderBuffer() {
glDeleteRenderbuffers(1, &mDepthBufferID);
}
uint4 RenderBuffer::texId() const {
return mTextureId;
}
uint4 RenderBuffer::texId() const { return mTextureId; }
const Vec2F& RenderBuffer::getSize() const { return mSize; }

View file

@ -13,14 +13,15 @@ namespace tp {
void geom_bind_source(const char* geom_src);
void compile();
void bind();
uint4 getu(const char* uid);
void unbind();
void load(const char* vert, const char* geom, const char* frag, bool paths);
private:
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
void load(const char* vert, const char* geom, const char* frag, bool paths);
private:
uint4 programm;

View file

@ -4,7 +4,7 @@ project(RayTracer)
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ../Externals/)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Connection)
### -------------------------- Applications -------------------------- ###

View file

@ -6,7 +6,7 @@ extern "C" {
#include "lualib.h"
}
#include "OBJ_Loader.h"
#include "obj/OBJ_Loader.h"
#include <filesystem>
@ -139,7 +139,6 @@ void loadScene(tp::Scene& scene, const std::string& scenePath, tp::RayTracer::Re
// Remove the filename from the path
fs::path directoryPath = fullPath.remove_filename();
if (luaL_dofile(L, scenePath.c_str()) != 0) {
lua_close(L);
printf("Cant open scene script.\n");

View file

@ -1,8 +1,8 @@
project(Sketch3D)
### ---------------------- Externals --------------------- ###
set(BINDINGS_INCLUDE ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
set(BINDINGS_LIBS glfw Imgui ${GLEW_LIB})
set(BINDINGS_INCLUDE ../Externals/glfw/include)
set(BINDINGS_LIBS glfw Imgui)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
@ -11,12 +11,12 @@ file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
target_link_libraries(${PROJECT_NAME} PUBLIC Graphics Connection Widgets Math)
target_link_libraries(${PROJECT_NAME} PUBLIC Graphics Connection Widgets Math RasterRender)
target_link_libraries(${PROJECT_NAME} PUBLIC ${BINDINGS_LIBS})
### -------------------------- Applications -------------------------- ###
add_executable(Sketch3DApp ./applications/Entry.cpp)
target_link_libraries(Sketch3DApp ${PROJECT_NAME})
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
file(COPY "applications/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -10,7 +10,12 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
### -------------------------- Applications -------------------------- ###
add_executable(ExampleGui examples/Entry.cpp)
target_link_libraries(ExampleGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(ExampleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(SimpleGui examples/SimpleGUI.cpp)
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(ChatGui examples/ChatGUI.cpp)
target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -0,0 +1,32 @@
#include "ChatGUI.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
class ExampleGUI : public Application {
public:
ExampleGUI() { mGui.setupConfig(mWidgetManager); }
void processFrame(EventHandler* eventHandler) override {
auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui.updateConfigCache(mWidgetManager);
mGui.proc(*eventHandler, rec, rec);
}
void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); }
private:
WidgetManager mWidgetManager;
ComplexWidget<EventHandler, Canvas> mGui;
};
int main() {
{
ExampleGUI gui;
gui.run();
}
}

View file

@ -7,15 +7,7 @@ namespace tp {
template <typename Events, typename Canvas>
class UserWidget : public Widget<Events, Canvas> {
public:
UserWidget() {
this->createConfig("User");
this->addColor("Base", "Base");
this->addValue("Size", "FontSize");
this->addValue("Padding", "Padding");
this->addColor("ColUser", "Front");
this->addColor("Accent", "Accent");
this->addValue("Rounding", "Rounding");
}
UserWidget() { this->mId = "UserWidget"; }
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
@ -28,34 +20,48 @@ namespace tp {
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
if (mIsHover) canvas.rect(this->mArea, this->getColor("Accent"), this->getValue("Rounding"));
else canvas.rect(this->mArea, this->getColor("Base"), this->getValue("Rounding"));
if (mIsHover) canvas.rect(this->mArea, mAccentColor, mRounding);
else canvas.rect(this->mArea, mBaseColor, mRounding);
const auto padding = this->getValue("Padding");
const auto size = this->getValue("Size");
const auto colUser = this->getColor("ColUser");
canvas.text(mUser.c_str(), this->mArea, mFontSize, Canvas::CC, mPadding, mUserColor);
}
canvas.text(mUser.c_str(), this->mArea, size, Canvas::CC, padding, colUser);
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Base", "Base");
wm.addReference(this->mId, "Size", "FontSize");
wm.addReference(this->mId, "Padding", "Padding");
wm.addReference(this->mId, "ColUser", "Front");
wm.addReference(this->mId, "Accent", "Accent");
wm.addReference(this->mId, "Rounding", "Rounding");
}
void updateConfigCache(const WidgetManager& wm) override {
mBaseColor = wm.getColor(this->mId, "Base");
mFontSize = wm.getNumber(this->mId, "Size");
mPadding = wm.getNumber(this->mId, "Padding");
mUserColor = wm.getColor(this->mId, "ColUser");
mAccentColor = wm.getColor(this->mId, "Accent");
mRounding = wm.getNumber(this->mId, "Rounding");
}
public:
std::string mUser = "UserName";
bool mIsHover = false;
RGBA mBaseColor;
RGBA mUserColor;
RGBA mAccentColor;
halnf mPadding = 0;
halnf mFontSize = 0;
halnf mRounding = 0;
};
template <typename Events, typename Canvas>
class MessageWidget : public Widget<Events, Canvas> {
public:
MessageWidget() {
this->createConfig("Message");
this->addColor("Base", "Base");
this->addValue("Size", "FontSize");
this->addValue("SizeUser", "FontSizeDim");
this->addValue("Padding", "Padding");
this->addColor("ColUser", "Front");
this->addColor("Col", "FrontDim");
this->addValue("Rounding", "Rounding");
}
MessageWidget() { this->mId = "MessageWidget"; }
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
@ -67,14 +73,7 @@ namespace tp {
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
if (mIsHover) canvas.rect(this->mArea, this->getColor("Base"), this->getValue("Rounding"));
const auto padding = this->getValue("Padding");
const auto size = this->getValue("Size");
const auto sizeUser = this->getValue("SizeUser");
const auto col = this->getColor("Col");
const auto colUser = this->getColor("ColUser");
if (mIsHover) canvas.rect(this->mArea, mBaseColor, mRounding);
auto userName = this->mArea;
userName.w = 25;
@ -83,22 +82,51 @@ namespace tp {
content.y = userName.y + userName.w;
content.w = this->mArea.w - userName.w;
canvas.text(mContent.c_str(), content, size, Canvas::LC, padding, col);
canvas.text(mUser.c_str(), userName, sizeUser, Canvas::LC, padding, colUser);
canvas.text(mContent.c_str(), content, mFontSize, Canvas::LC, mPadding, mUserColorDim);
canvas.text(mUser.c_str(), userName, mFontSizeDim, Canvas::LC, mPadding, mUserColor);
}
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Base", "Base");
wm.addReference(this->mId, "Size", "FontSize");
wm.addReference(this->mId, "SizeUser", "FontSizeDim");
wm.addReference(this->mId, "Padding", "Padding");
wm.addReference(this->mId, "UserColor", "Front");
wm.addReference(this->mId, "UserColorDim", "FrontDim");
wm.addReference(this->mId, "Rounding", "Rounding");
}
void updateConfigCache(const WidgetManager& wm) override {
mBaseColor = wm.getColor(this->mId, "Base");
mFontSize = wm.getNumber(this->mId, "Size");
mFontSizeDim = wm.getNumber(this->mId, "SizeUser");
mPadding = wm.getNumber(this->mId, "Padding");
mUserColor = wm.getColor(this->mId, "UserColor");
mUserColorDim = wm.getColor(this->mId, "UserColorDim");
mRounding = wm.getNumber(this->mId, "Rounding");
}
public:
std::string mContent = "Message Content";
std::string mUser = "UserName";
bool mIsHover = false;
RGBA mBaseColor;
RGBA mUserColor;
RGBA mUserColorDim;
halnf mPadding = 0;
halnf mFontSize = 0;
halnf mFontSizeDim = 0;
halnf mRounding = 0;
};
template <typename Events, typename Canvas>
class LoginWidget : public Widget<Events, Canvas> {
public:
explicit LoginWidget() {
this->createConfig("Login");
this->addColor("Back", "Background");
this->mId = "Login";
mPass.mId = "pass";
mUser.mId = "user";
mButton.mLabel.mLabel = "Login";
@ -120,26 +148,45 @@ namespace tp {
}
void draw(Canvas& canvas) override {
canvas.rect(this->mArea, this->getColor("Back"));
canvas.rect(this->mArea, mBGColor);
mButton.draw(canvas);
mUser.draw(canvas);
mPass.draw(canvas);
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Back", "Base");
mUser.setupConfig(wm);
mPass.setupConfig(wm);
mButton.setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
mBGColor = wm.getColor(this->mId, "Back");
mUser.updateConfigCache(wm);
mPass.updateConfigCache(wm);
mButton.updateConfigCache(wm);
}
public:
TextInputWidget<Events, Canvas> mUser;
TextInputWidget<Events, Canvas> mPass;
ButtonWidget<Events, Canvas> mButton;
bool mLogged = false;
RGBA mBGColor;
};
template <typename Events, typename Canvas>
class ActiveChatWidget : public Widget<Events, Canvas> {
public:
ActiveChatWidget() {
this->createConfig("ActiveChat");
this->addColor("Back", "Background");
this->addValue("Padding", "Padding");
this->mId = "ActiveWidget";
mSend.mLabel.mLabel = "Send";
mMessage.mId = "Message";
}
@ -152,16 +199,16 @@ namespace tp {
auto input = this->mArea;
input.y = history.w + 10;
input.w = 40 - this->getValue("Padding");
input.x += this->getValue("Padding");
input.z -= this->getValue("Padding");
input.w = 40 - mPadding;
input.x += mPadding;
input.z -= mPadding;
auto inputMessage = input;
inputMessage.z -= 100;
auto inputSend = input;
inputSend.x = inputMessage.x + inputMessage.z + this->getValue("Padding");
inputSend.z = 100 - this->getValue("Padding") * 2;
inputSend.x = inputMessage.x + inputMessage.z + mPadding;
inputSend.z = 100 - mPadding * 2;
mSend.proc(events, this->mArea, inputSend);
mMessage.proc(events, this->mArea, inputMessage);
@ -174,26 +221,53 @@ namespace tp {
}
void draw(Canvas& canvas) override {
canvas.rect(this->mArea, this->getColor("Back"));
canvas.rect(this->mArea, mBGColor);
mHistoryView.draw(canvas);
mMessage.draw(canvas);
mSend.draw(canvas);
}
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Back", "Background");
wm.addReference(this->mId, "Padding", "Padding");
mHistoryView.setupConfig(wm);
mMessage.setupConfig(wm);
mSend.setupConfig(wm);
MessageWidget<Events, Canvas>().setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
mBGColor = wm.getColor(this->mId, "Back");
mPadding = wm.getNumber(this->mId, "Padding");
mHistoryView.updateConfigCache(wm);
mMessage.updateConfigCache(wm);
mSend.updateConfigCache(wm);
for (auto message : mMessages) {
message->updateConfigCache(wm);
}
}
public:
Buffer<MessageWidget<Events, Canvas>> mMessages;
ScrollableWindow<Events, Canvas> mHistoryView;
TextInputWidget<Events, Canvas> mMessage;
ButtonWidget<Events, Canvas> mSend;
RGBA mBGColor;
halnf mPadding = 0;
};
template <typename Events, typename Canvas>
class ChattingWidget : public Widget<Events, Canvas> {
public:
ChattingWidget() {
this->createConfig("Chatting");
this->addColor("Back", "Background");
this->addValue("Padding", "Padding");
this->mId = "Chatting";
// todo : fetch code
mUsers.append(UserWidget<Events, Canvas>());
@ -225,34 +299,54 @@ namespace tp {
this->mArea = aArea;
mSplitView.proc(events, aArea, aArea);
const auto padding = this->getValue("Padding");
mSideView.proc(events, this->mArea, mSplitView.getSecond());
mActive.proc(events, aArea, mSplitView.getFirst());
}
void draw(Canvas& canvas) override {
canvas.rect(this->mArea, this->getColor("Back"));
canvas.rect(this->mArea, mBGColor);
mSplitView.draw(canvas);
mSideView.draw(canvas);
mActive.draw(canvas);
}
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Back", "Background");
mSideView.setupConfig(wm);
mActive.setupConfig(wm);
mSplitView.setupConfig(wm);
UserWidget<Events, Canvas>().setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
mBGColor = wm.getColor(this->mId, "Back");
mSideView.updateConfigCache(wm);
mActive.updateConfigCache(wm);
mSplitView.updateConfigCache(wm);
for (auto user : mUsers) {
user->updateConfigCache(wm);
}
}
public:
Buffer<UserWidget<Events, Canvas>> mUsers;
ScrollableWindow<Events, Canvas> mSideView;
ActiveChatWidget<Events, Canvas> mActive;
SplitView<Events, Canvas> mSplitView;
RGBA mBGColor;
};
template <typename Events, typename Canvas>
class ComplexWidget : public Widget<Events, Canvas> {
public:
ComplexWidget() {
this->createConfig("chat");
this->addColor("Back", "Background");
}
ComplexWidget() { this->mId = "Chat"; }
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
this->mArea = aArea;
@ -268,14 +362,32 @@ namespace tp {
}
void draw(Canvas& canvas) override {
canvas.rect(this->mArea, this->getColor("Back"));
canvas.rect(this->mArea, mBGColor);
if (mLogged) mChatting.draw(canvas);
else mLogin.draw(canvas);
}
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Back", "Background");
mLogin.setupConfig(wm);
mChatting.setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
mBGColor = wm.getColor(this->mId, "Back");
mLogin.updateConfigCache(wm);
mChatting.updateConfigCache(wm);
}
private:
bool mLogged = false;
LoginWidget<Events, Canvas> mLogin;
ChattingWidget<Events, Canvas> mChatting;
RGBA mBGColor;
};
}

View file

@ -1,33 +0,0 @@
#include "ExampleGUI.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
class ExampleGUI : public Application {
public:
ExampleGUI() = default;
void processFrame(EventHandler* eventHandler) override {
auto rec = RectF( { 0, 0 }, mWindow->getSize() );
mGui.proc(*eventHandler, rec, rec);
}
void drawFrame(Canvas* canvas) override {
mGui.draw(*canvas);
}
private:
ComplexWidget<EventHandler, Canvas> mGui;
};
int main() {
GlobalGUIConfig mConfig;
gGlobalGUIConfig = &mConfig;
{
ExampleGUI gui;
gui.run();
}
}

View file

@ -0,0 +1,50 @@
#include "ChatGUI.hpp"
#include "GraphicApplication.hpp"
using namespace tp;
class SimpleGUI : public Application {
public:
SimpleGUI() {
mGui.setupConfig(mWidgetManager);
mButton.setupConfig(mWidgetManager);
mSlider.setupConfig(mWidgetManager);
mLabel.setupConfig(mWidgetManager);
mGui.mContents.append(&mButton);
mGui.mContents.append(&mSlider);
mGui.mContents.append(&mLabel);
}
void processFrame(EventHandler* eventHandler) override {
mGui.updateConfigCache(mWidgetManager);
mSlider.updateConfigCache(mWidgetManager);
mLabel.updateConfigCache(mWidgetManager);
mButton.updateConfigCache(mWidgetManager);
const auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui.proc(*eventHandler, rec, rec);
}
void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); }
private:
WidgetManager mWidgetManager;
ScrollableWindow<EventHandler, Canvas> mGui;
ButtonWidget<EventHandler, Canvas> mButton;
LabelWidget<EventHandler, Canvas> mLabel;
SliderWidget<EventHandler, Canvas> mSlider;
};
int main() {
{
SimpleGUI gui;
gui.run();
}
}

View file

@ -3,6 +3,4 @@
#include "Graphics.hpp"
namespace tp {
GlobalGUIConfig* gGlobalGUIConfig = nullptr;
}
namespace tp {}

View file

@ -9,22 +9,13 @@ namespace tp {
public:
ButtonWidget() {
this->mArea = { 0, 0, 100, 100 };
this->createConfig("Button");
this->addColor("Pressed", "Action");
this->addColor("Hovered", "Interaction");
this->addColor("Default", "Accent");
this->addValue("Rounding", "Rounding");
this->mId = "Button";
}
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
this->mId = "Button";
this->mArea = aArea;
this->mLabel.mLabel = label;
this->createConfig("Button");
this->addColor("Pressed", "Action");
this->addColor("Hovered", "Interaction");
this->addColor("Default", "Accent");
this->addValue("Rounding", "Rounding");
}
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
@ -60,19 +51,45 @@ namespace tp {
if (!this->mVisible) return;
if (mIsPressed) {
canvas.rect(this->mArea, this->getColor("Pressed"), this->getValue("Rounding"));
canvas.rect(this->mArea, pressedColor, rounding);
} else if (mIsHover) {
canvas.rect(this->mArea, this->getColor("Hovered"), this->getValue("Rounding"));
canvas.rect(this->mArea, hoveredColor, rounding);
} else {
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
canvas.rect(this->mArea, accentColor, rounding);
}
mLabel.draw(canvas);
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Pressed", "Action");
wm.addReference(this->mId, "Hovered", "Interaction");
wm.addReference(this->mId, "Default", "Accent");
wm.addReference(this->mId, "Rounding", "Rounding");
mLabel.setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
pressedColor = wm.getColor(this->mId, "Pressed");
hoveredColor = wm.getColor(this->mId, "Hovered");
accentColor = wm.getColor(this->mId, "Default");
rounding = wm.getNumber(this->mId, "Rounding");
mLabel.updateConfigCache(wm);
}
public:
LabelWidget<Events, Canvas> mLabel;
bool mIsHover = false;
bool mIsPressed = false;
bool mIsReleased = false;
RGBA pressedColor;
RGBA hoveredColor;
RGBA accentColor;
halnf rounding = 0;
};
}

View file

@ -6,14 +6,9 @@ namespace tp {
template <typename Events, typename Canvas>
class LabelWidget : public Widget<Events, Canvas> {
public:
LabelWidget() {
this->createConfig("Label");
this->addValue("Size", "FontSize");
this->addValue("Padding", "Padding");
this->addColor("Default", "Front");
}
LabelWidget() { this->mId = "Label"; }
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
void proc(const Events&, const tp::RectF& areaParent, const tp::RectF& aArea) override {
this->mArea = aArea;
this->mVisible = areaParent.isOverlap(aArea);
if (!this->mVisible) return;
@ -21,18 +16,28 @@ namespace tp {
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor);
}
canvas.text(
mLabel.c_str(),
this->mArea,
this->getValue("Size"),
Canvas::CC,
this->getValue("Padding"),
this->getColor("Default")
);
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Size", "FontSize");
wm.addReference(this->mId, "Padding", "Padding");
wm.addReference(this->mId, "Default", "Front");
}
void updateConfigCache(const WidgetManager& wm) override {
fontSize = wm.getNumber(this->mId, "Size");
padding = wm.getNumber(this->mId, "Padding");
fontColor = wm.getColor(this->mId, "Default");
}
public:
std::string mLabel = "Label";
halnf fontSize = 10;
halnf padding = 0;
RGBA fontColor = { 1, 1, 1, 1 };
};
}

View file

@ -8,17 +8,7 @@ namespace tp {
template <typename Events, typename Canvas>
class ScrollBarWidget : public Widget<Events, Canvas> {
public:
ScrollBarWidget() {
this->createConfig("ScrollBar");
this->addColor("Default", "Base");
this->addColor("Handle", "Accent");
this->addColor("Hovered", "Interaction");
this->addColor("Scrolling", "Action");
this->addValue("Padding", "Padding");
this->addValue("HandleSize", 20.f);
this->addValue("MinSize", 20.f);
this->addValue("Rounding", "Rounding");
}
ScrollBarWidget() { this->mId = "ScrollBar"; }
// takes whole area
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
@ -79,28 +69,22 @@ namespace tp {
if (mSizeFraction > 1.f) return;
// if (!areaParent.isOverlap(getHandle())) return;
tp::RGBA col = this->getColor("Handle");
tp::RGBA col = mHandleColor;
if (mIsScrolling) {
col = this->getColor("Scrolling");
col = mScrollingColor;
} else if (mHovered) {
col = this->getColor("Hovered");
col = mHoveredColor;
}
canvas.rect(area, this->getColor("Default"), this->getValue("Rounding"));
canvas.rect(area, mDefaultColor, mRounding);
canvas.rect(getHandleHandle(), col, this->getValue("Rounding"));
canvas.rect(getHandleHandle(), col, mRounding);
}
RectF getHandleHandle() const {
auto minSize = this->getValue("MinSize");
if (mIsScrolling) {
minSize = this->getValue("MinSize") * 2;
} else if (mHovered) {
minSize = this->getValue("MinSize") * 2;
}
auto area = getHandle();
auto sliderSize = tp::clamp(area.w * mSizeFraction, minSize, area.w);
auto sliderSize = tp::clamp(area.w * mSizeFraction, mMinSize * 2, area.w);
auto diffSize = sliderSize - area.w * mSizeFraction;
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
}
@ -109,14 +93,39 @@ namespace tp {
if (mSizeFraction > 1.f) {
return this->mArea;
}
return { this->mArea.x, this->mArea.y, this->mArea.z - this->getValue("HandleSize"), this->mArea.w };
return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w };
}
RectF getHandle() const {
return { this->mArea.x + this->mArea.z - this->getValue("HandleSize") + this->getValue("Padding"),
this->mArea.y + this->getValue("Padding"),
this->getValue("HandleSize") - this->getValue("Padding") * 2,
this->mArea.w - this->getValue("Padding") * 2 };
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
this->mArea.y + mPadding,
mHandleSize - mPadding * 2,
this->mArea.w - mPadding * 2 };
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Default", "Base");
wm.addReference(this->mId, "Handle", "Accent");
wm.addReference(this->mId, "Hovered", "Interaction");
wm.addReference(this->mId, "Scrolling", "Action");
wm.addReference(this->mId, "Padding", "Padding");
wm.addNumber(this->mId, "HandleSize", 20.f);
wm.addNumber(this->mId, "MinSize", 20.f);
wm.addReference(this->mId, "Rounding", "Rounding");
}
void updateConfigCache(const WidgetManager& wm) override {
mDefaultColor = wm.getColor(this->mId, "Default");
mHandleColor = wm.getColor(this->mId, "Handle");
mHoveredColor = wm.getColor(this->mId, "Hovered");
mScrollingColor = wm.getColor(this->mId, "Scrolling");
mPadding = wm.getNumber(this->mId, "Padding");
mHandleSize = wm.getNumber(this->mId, "HandleSize");
mMinSize = wm.getNumber(this->mId, "MinSize");
mRounding = wm.getNumber(this->mId, "Rounding");
}
public:
@ -126,16 +135,21 @@ namespace tp {
halnf mSizeFraction = 1.f;
halnf mPositionFraction = 0.f;
bool mHovered = false;
RGBA mDefaultColor;
RGBA mHandleColor;
RGBA mHoveredColor;
RGBA mScrollingColor;
halnf mPadding = 0;
halnf mHandleSize = 10;
halnf mMinSize = 10;
halnf mRounding = 10;
};
template <typename Events, typename Canvas>
class ScrollableWindow : public Widget<Events, Canvas> {
public:
ScrollableWindow() {
this->createConfig("ScrollableWindow");
this->addColor("Default", "Base");
this->addValue("Padding", "Padding");
}
ScrollableWindow() { this->mId = "ScrollableWindow"; }
~ScrollableWindow() = default;
@ -148,7 +162,7 @@ namespace tp {
updateContents();
updateContentSize();
const auto padding = this->getValue("Padding");
const auto padding = mPadding;
mScroller.mSizeFraction = this->mArea.w / mContentSize;
mScroller.proc(events, this->mArea, this->mArea);
@ -180,16 +194,37 @@ namespace tp {
canvas.popClamp();
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Default", "Base");
wm.addReference(this->mId, "Padding", "Padding");
wm.addReference(this->mId, "Rounding", "Rounding");
mScroller.setupConfig(wm);
}
void updateConfigCache(const WidgetManager& wm) override {
mDefaultColor = wm.getColor(this->mId, "Default");
mPadding = wm.getNumber(this->mId, "Padding");
mScroller.updateConfigCache(wm);
for (auto item : mContents) {
item->updateConfigCache(wm);
}
}
private:
void updateContents() {
if (mContents.size()) {
const auto padding = this->getValue("Padding");
const halnf offset = mContents.first()->mArea.y + padding;
const halnf offset = mContents.first()->mArea.y + mPadding;
halnf start = 0;
for (auto widget : mContents) {
widget->mArea.y = start;
start += widget->mArea.w + padding;
start += widget->mArea.w + mPadding;
}
for (auto widget : mContents) {
@ -201,17 +236,15 @@ namespace tp {
void updateContentSize() {
mContentSize = 0;
if (mContents.size()) {
const auto padding = this->getValue("Padding");
mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y;
mContentSize += mContents.last()->mArea.w;
mContentSize += 2 * padding;
mContentSize += 2 * mPadding;
}
}
void setOffset(const halnf offset) {
if (!mContents.size()) return;
const auto padding = this->getValue("Padding");
auto newOffset = offset - mContents.first()->mArea.y + padding;
auto newOffset = offset - mContents.first()->mArea.y + mPadding;
for (auto widget : mContents) {
widget->mArea.y += newOffset;
}
@ -219,7 +252,11 @@ namespace tp {
public:
halnf mContentSize = 0;
Buffer<Widget<Events, Canvas>*> mContents;
ScrollBarWidget<Events, Canvas> mScroller;
RGBA mDefaultColor;
halnf mPadding = 0;
};
}

View file

@ -7,17 +7,7 @@ namespace tp {
template <typename Events, typename Canvas>
class SliderWidget : public Widget<Events, Canvas> {
public:
SliderWidget() {
this->createConfig("SliderWidget");
this->addColor("Default", "Base");
this->addColor("Handle", "Accent");
this->addColor("Hovered", "Interaction");
this->addColor("Scrolling", "Action");
this->addValue("Padding", "Padding");
this->addValue("HandleSize", 20.f);
this->addValue("MinSize", 20.f);
this->addValue("Rounding", "Rounding");
}
SliderWidget() { this->mId = "SliderWidget"; }
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
this->mArea = aArea;
@ -31,7 +21,6 @@ namespace tp {
}
if (mIsSliding) {
const auto handleSize = this->getValue("HandleSize");
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
}
@ -40,26 +29,47 @@ namespace tp {
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
canvas.rect(getHandle(), this->getColor("Handle"), this->getValue("Rounding"));
canvas.rect(this->mArea, defaultColor, rounding);
canvas.rect(getHandle(), handleColor, rounding);
}
RectF getHandle() const {
const auto handle = this->getValue("HandleSize");
const auto halfHandle = handle / 2.f;
const auto left = this->mArea.x + (this->mArea.z - handle) * mFactor;
return { left, this->mArea.y, handle, this->mArea.w };
const auto halfHandle = handleSize / 2.f;
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
return { left, this->mArea.y, handleSize, this->mArea.w };
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Default", "Base");
wm.addReference(this->mId, "Handle", "Accent");
wm.addNumber(this->mId, "HandleSize", 20.f);
wm.addReference(this->mId, "Rounding", "Rounding");
}
void updateConfigCache(const WidgetManager& wm) override {
defaultColor = wm.getColor(this->mId, "Default");
handleColor = wm.getColor(this->mId, "Handle");
handleSize = wm.getNumber(this->mId, "HandleSize");
rounding = wm.getNumber(this->mId, "Rounding");
}
public:
halnf mFactor = 0.f;
bool mIsSliding = false;
RGBA defaultColor;
RGBA handleColor;
halnf handleSize = 0;
halnf rounding = 0;
};
template <typename Events, typename Canvas>
class NamedSliderWidget : public Widget<Events, Canvas> {
public:
NamedSliderWidget(const char* name = "Value") {
explicit NamedSliderWidget(const char* name = "Value") {
this->mId = "NamedSliderWidget";
mLabel.mLabel = name;
this->mArea = { 0, 0, 100, 30 };
}
@ -89,6 +99,7 @@ namespace tp {
mLabel.draw(canvas);
}
public:
public:
SliderWidget<Events, Canvas> mSlider;
LabelWidget<Events, Canvas> mLabel;

View file

@ -6,14 +6,7 @@ namespace tp {
template <typename Events, typename Canvas>
class SplitView : public Widget<Events, Canvas> {
public:
SplitView() {
this->createConfig("SplitView");
this->addColor("Handle", "Accent");
this->addColor("Hovered", "Interaction");
this->addColor("Resizing", "Action");
this->addValue("Min", 200.f);
this->addValue("HandleSize", 7.f);
}
SplitView() { this->mId = "SplitView"; }
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
this->mArea = aArea;
@ -38,9 +31,9 @@ namespace tp {
mFactor += diff / this->mArea.z;
}
mFactor = tp::clamp(mFactor, this->getValue("Min") / this->mArea.z, 1 - this->getValue("Min") / this->mArea.z);
mFactor = tp::clamp(mFactor, mMinSize / this->mArea.z, 1 - mMinSize / this->mArea.z);
if (this->getValue("Min") * 2.f > this->mArea.z) {
if (mMinSize * 2.f > this->mArea.z) {
mFactor = 0.5f;
}
}
@ -49,34 +42,52 @@ namespace tp {
void draw(Canvas& canvas) override {
if (!this->mVisible) return;
if (mResizeInProcess) canvas.rect(getHandle(), this->getColor("Resizing"));
else if (mIsHover) canvas.rect(getHandle(), this->getColor("Hovered"));
else canvas.rect(getHandle(), this->getColor("Handle"));
if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor);
else if (mIsHover) canvas.rect(getHandle(), mHoveredColor);
else canvas.rect(getHandle(), mHandleColor);
}
RectF getFirst() const {
return {
this->mArea.x, this->mArea.y, mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f, this->mArea.w
};
return { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.w };
}
RectF getSecond() const {
return { this->mArea.x + mFactor * this->mArea.z + this->getValue("HandleSize") / 2.f,
return { this->mArea.x + mFactor * this->mArea.z + mHandleSize / 2.f,
this->mArea.y,
(1.f - mFactor) * this->mArea.z - this->getValue("HandleSize") / 2.f,
(1.f - mFactor) * this->mArea.z - mHandleSize / 2.f,
this->mArea.w };
}
RectF getHandle() const {
return { this->mArea.x + mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f,
this->mArea.y,
this->getValue("HandleSize"),
this->mArea.w };
return { this->mArea.x + mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.y, mHandleSize, this->mArea.w };
}
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Handle", "Accent");
wm.addReference(this->mId, "Hovered", "Interaction");
wm.addReference(this->mId, "Resizing", "Action");
wm.addNumber(this->mId, "Min", 200.f);
wm.addNumber(this->mId, "HandleSize", 7.f);
}
void updateConfigCache(const WidgetManager& wm) override {
mHandleColor = wm.getColor(this->mId, "Handle");
mHoveredColor = wm.getColor(this->mId, "Hovered");
mResizingColor = wm.getColor(this->mId, "Resizing");
mMinSize = wm.getNumber(this->mId, "Min");
mHandleSize = wm.getNumber(this->mId, "HandleSize");
}
public:
halnf mFactor = 0.7f;
bool mResizeInProcess = false;
bool mIsHover = false;
RGBA mHandleColor;
RGBA mHoveredColor;
RGBA mResizingColor;
halnf mMinSize = 0;
halnf mHandleSize = 0;
};
}

View file

@ -9,14 +9,7 @@ namespace tp {
template <typename Events, typename Canvas>
class TextInputWidget : public Widget<Events, Canvas> {
public:
TextInputWidget() {
this->createConfig("TextInput");
this->addColor("Accent", "Accent");
this->addColor("Base", "Base");
this->addValue("Rounding", "Rounding");
this->addColor("Hovered", "Interaction");
this->addValue("Padding", "Padding");
}
TextInputWidget() { this->mId = "TextInput"; }
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
this->mArea = aArea;
@ -29,8 +22,8 @@ namespace tp {
nChanged = false;
const auto col = this->getColor("Accent");
const auto colSel = this->getColor("Hovered");
const auto col = mAccentColor;
const auto colSel = mHoveredColor;
ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a };
ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a };
@ -38,8 +31,8 @@ namespace tp {
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, this->getValue("Rounding") * 1.5f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { this->getValue("Padding"), this->getValue("Padding") });
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
// ImGui::PushID((int) alni(this));
ImGui::Begin(
@ -65,11 +58,36 @@ namespace tp {
ImGui::PopStyleVar(3);
}
public:
void setupConfig(WidgetManager& wm) {
if (!wm.createWidgetConfig(this->mId)) return;
wm.addReference(this->mId, "Accent", "Accent");
wm.addReference(this->mId, "Base", "Base");
wm.addReference(this->mId, "Rounding", "Rounding");
wm.addReference(this->mId, "Hovered", "Accent");
wm.addReference(this->mId, "Padding", "Padding");
}
void updateConfigCache(const WidgetManager& wm) override {
mAccentColor = wm.getColor(this->mId, "Accent");
mBaseColor = wm.getColor(this->mId, "Base");
mHoveredColor = wm.getColor(this->mId, "Hovered");
mRounding = wm.getNumber(this->mId, "Rounding");
mPadding = wm.getNumber(this->mId, "Padding");
}
public:
enum { mMaxBufferSize = 512 };
char mBuff[mMaxBufferSize] = "";
bool nChanged = false;
std::string mValue;
std::string mId = "id";
bool mMultiline = false;
RGBA mAccentColor;
RGBA mHoveredColor;
RGBA mBaseColor;
halnf mRounding = 0;
halnf mPadding = 0;
};
}

View file

@ -1,46 +1,13 @@
#pragma once
#include "WidgetConfig.hpp"
#include "WidgetManager.hpp"
namespace tp {
template <typename Events, typename Canvas>
class Widget {
public:
Widget() {
this->mArea = { 0, 0, 100, 100 };
}
[[nodiscard]] const RGBA& getColor(const std::string& name) const {
const auto& node = cfg->values.get(name);
if (node.type == WidgetConfig::Node::REF) {
return globalCfg->configs.get(node.refGroup).values.get(node.refName).color;
}
return cfg->values.get(name).color;
}
[[nodiscard]] halnf getValue(const std::string& name) const {
const auto& node = cfg->values.get(name);
if (node.type == WidgetConfig::Node::REF) {
return globalCfg->configs.get(node.refGroup).values.get(node.refName).value;
}
return cfg->values.get(name).value;
}
void addColor(const std::string& name, const RGBA& val) { cfg->values.put(name, WidgetConfig::Node(val)); }
void addValue(const std::string& name, halnf val) { cfg->values.put(name, WidgetConfig::Node(val)); }
void addColor(const std::string& name, const std::string& presetName) {
cfg->values.put(name, WidgetConfig::Node(presetName));
}
void addValue(const std::string& name, const std::string& presetName) {
cfg->values.put(name, WidgetConfig::Node(presetName));
}
void createConfig(const std::string& name) {
globalCfg->configs.put(name, {});
cfg = &globalCfg->configs.get(name);
}
Widget() { this->mArea = { 0, 0, 100, 100 }; }
virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
mVisible = areaParent.isOverlap(aArea);
@ -57,9 +24,10 @@ namespace tp {
}
}
virtual void updateConfigCache(const WidgetManager& wm) = 0;
public:
GlobalGUIConfig* globalCfg = gGlobalGUIConfig;
WidgetConfig* cfg = nullptr;
std::string mId;
RectF mArea;
bool mVisible = false;
};

View file

@ -1,73 +0,0 @@
#pragma once
#include "Animations.hpp"
#include "Map.hpp"
#include "Rect.hpp"
#include "InputCodes.hpp"
namespace tp {
struct WidgetConfig {
struct Node {
enum Type { NONE, VAL, COL, REF };
halnf value = 0.f;
RGBA color = {};
Type type = NONE;
std::string refGroup;
std::string refName;
Node() = default;
explicit Node(halnf val) {
type = VAL;
value = val;
}
explicit Node(const RGBA& val) {
type = COL;
color = val;
}
explicit Node(const std::string& val) {
refGroup = "Presets";
refName = val;
type = REF;
}
};
Map<std::string, Node> values;
};
struct GlobalGUIConfig {
GlobalGUIConfig() {
configs.put("Presets", {});
auto& presets = configs.get("Presets");
presets.values.put("FontSize", WidgetConfig::Node(15.f));
presets.values.put("FontSizeDim", WidgetConfig::Node(12.f));
presets.values.put("Rounding", WidgetConfig::Node(5.f));
presets.values.put("Padding", WidgetConfig::Node(5.f));
presets.values.put("HandleSize", WidgetConfig::Node(5.f));
presets.values.put("Background", WidgetConfig::Node(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
presets.values.put("Base", WidgetConfig::Node(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
presets.values.put("Accent", WidgetConfig::Node(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
presets.values.put("Interaction", WidgetConfig::Node(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
presets.values.put("Action", WidgetConfig::Node(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
presets.values.put("Front", WidgetConfig::Node(RGBA{ 1.f, 1.f, 1.f, 1.f }));
presets.values.put("FrontDim", WidgetConfig::Node(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
}
Map<std::string, WidgetConfig> configs;
~GlobalGUIConfig() {
configs.removeAll();
}
};
extern GlobalGUIConfig* gGlobalGUIConfig;
}

View file

@ -0,0 +1,131 @@
#pragma once
#include "Animations.hpp"
#include "Map.hpp"
#include "Rect.hpp"
#include "InputCodes.hpp"
#include "Buffer.hpp"
namespace tp {
struct WidgetConfig {
struct WidgetShortcut {
struct Condition {
std::string name;
std::string state;
};
std::string callbackName;
WidgetShortcut() = default;
WidgetShortcut(const InitialierList<Condition>&) {}
};
struct WidgetParameter {
enum Type { NONE, VAL, COL, REF };
halnf value = 0.f;
RGBA color = {};
std::string refName;
std::string refWidgetId;
Type type = NONE;
WidgetParameter() = default;
explicit WidgetParameter(halnf val) {
type = VAL;
value = val;
}
explicit WidgetParameter(const RGBA& val) {
type = COL;
color = val;
}
explicit WidgetParameter(const std::string& widgetId, const std::string& val) {
type = REF;
refName = val;
refWidgetId = widgetId;
}
};
Map<std::string, WidgetParameter> mParameters;
Buffer<WidgetShortcut> mShortcuts;
};
class WidgetManager {
public:
WidgetManager() {
createWidgetConfig("Default");
addNumber("Default", "FontSize", 15.f);
addNumber("Default", "FontSizeDim", 12.f);
addNumber("Default", "Rounding", 5.f);
addNumber("Default", "Padding", 5.f);
addNumber("Default", "HandleSize", 5.f);
addColor("Default", "Background", RGBA{ 0.03f, 0.03f, 0.03f, 1.f });
addColor("Default", "Base", RGBA{ 0.07f, 0.07f, 0.07f, 1.f });
addColor("Default", "Accent", RGBA{ 0.13f, 0.13f, 0.13f, 1.f });
addColor("Default", "Interaction", RGBA{ 0.33f, 0.33f, 0.3f, 1.f });
addColor("Default", "Action", RGBA{ 0.44f, 0.44f, 0.4f, 1.f });
addColor("Default", "Front", RGBA{ 1.f, 1.f, 1.f, 1.f });
addColor("Default", "FrontDim", RGBA{ 0.7f, 0.7f, 0.7f, 1.f });
}
~WidgetManager() { mConfigurations.removeAll(); }
bool createWidgetConfig(const std::string& widgetId) {
auto idx = mConfigurations.presents(widgetId);
if (idx) return false;
mConfigurations.put(widgetId, {});
return true;
}
[[nodiscard]] const RGBA& getColor(const std::string& widgetId, const std::string& name) const {
const WidgetConfig& config = mConfigurations.get(widgetId);
const WidgetConfig::WidgetParameter& parameter = config.mParameters.get(name);
if (parameter.type == WidgetConfig::WidgetParameter::REF) {
return mConfigurations.get(parameter.refWidgetId).mParameters.get(parameter.refName).color;
} else {
return parameter.color;
}
}
[[nodiscard]] halnf getNumber(const std::string& widgetId, const std::string& name) const {
const WidgetConfig& config = mConfigurations.get(widgetId);
const WidgetConfig::WidgetParameter& parameter = config.mParameters.get(name);
if (parameter.type == WidgetConfig::WidgetParameter::REF) {
return mConfigurations.get(parameter.refWidgetId).mParameters.get(parameter.refName).value;
} else {
return parameter.value;
}
}
void addColor(const std::string& widgetId, const std::string& name, const RGBA& val) {
WidgetConfig& config = mConfigurations.get(widgetId);
config.mParameters.put(name, WidgetConfig::WidgetParameter(val));
}
void addNumber(const std::string& widgetId, const std::string& name, halnf val) {
WidgetConfig& config = mConfigurations.get(widgetId);
config.mParameters.put(name, WidgetConfig::WidgetParameter(val));
}
void addReference(const std::string& widgetId, const std::string& refName, const std::string& name) {
WidgetConfig& config = mConfigurations.get(widgetId);
config.mParameters.put(refName, WidgetConfig::WidgetParameter("Default", name));
}
private:
Map<std::string, WidgetConfig> mConfigurations;
RGBA mErrorColor = { 0, 0, 0, 1 };
halnf mErrorNumber = 0;
};
}