Update widgets module. Raster example initial.
This commit is contained in:
parent
9e339defd6
commit
9cfae3fe3e
48 changed files with 1169 additions and 530 deletions
22
3DEditor/CMakeLists.txt
Normal file
22
3DEditor/CMakeLists.txt
Normal 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}/")
|
||||||
43
3DEditor/applications/Entry.cpp
Normal file
43
3DEditor/applications/Entry.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
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->updateConfigCache(mWidgetManager);
|
||||||
|
mGui->proc(*eventHandler, rec, rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawFrame(Canvas* canvas) override { mGui->draw(*canvas); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Scene geometry;
|
||||||
|
WidgetManager mWidgetManager;
|
||||||
|
EditorWidget<EventHandler, Canvas>* mGui;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
EditorGUI gui;
|
||||||
|
gui.run();
|
||||||
|
}
|
||||||
41
3DEditor/applications/SceneLoad.cpp
Normal file
41
3DEditor/applications/SceneLoad.cpp
Normal 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
110
3DEditor/private/Render.cpp
Normal 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();
|
||||||
|
}
|
||||||
79
3DEditor/public/EditorWidget.hpp
Normal file
79
3DEditor/public/EditorWidget.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include "Widgets.hpp"
|
||||||
|
#include "Render.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
template <typename Events, typename Canvas>
|
||||||
|
class ViewportWidget : public Widget<Events, Canvas> {
|
||||||
|
public:
|
||||||
|
explicit ViewportWidget(Canvas* canvas, Scene* geometry, Vec2F renderResolution) :
|
||||||
|
mRender(renderResolution) {
|
||||||
|
|
||||||
|
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) {}
|
||||||
|
|
||||||
|
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, mBaseColor);
|
||||||
|
mSplitView.draw(canvas);
|
||||||
|
mViewport.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("3DEditor");
|
||||||
|
|
||||||
|
mBaseColor = wm.getColor("Base", "Base");
|
||||||
|
|
||||||
|
mViewport.updateConfigCache(wm);
|
||||||
|
mSplitView.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ViewportWidget<Events, Canvas> mViewport;
|
||||||
|
SplitView<Events, Canvas> mSplitView;
|
||||||
|
|
||||||
|
RGBA mBaseColor;
|
||||||
|
};
|
||||||
|
}
|
||||||
23
3DEditor/public/Render.hpp
Normal file
23
3DEditor/public/Render.hpp
Normal 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
34
3DEditor/public/Scene.hpp
Normal 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
BIN
3DEditor/rsc/Font.ttf
Normal file
Binary file not shown.
112
3DEditor/rsc/scene.obj
Normal file
112
3DEditor/rsc/scene.obj
Normal 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
|
||||||
7
3DEditor/rsc/shaders/default.frag
Normal file
7
3DEditor/rsc/shaders/default.frag
Normal 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);
|
||||||
|
}
|
||||||
11
3DEditor/rsc/shaders/default.vert
Normal file
11
3DEditor/rsc/shaders/default.vert
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -22,4 +22,6 @@ add_subdirectory(DataAnalysis)
|
||||||
add_subdirectory(Objects)
|
add_subdirectory(Objects)
|
||||||
add_subdirectory(Widgets)
|
add_subdirectory(Widgets)
|
||||||
add_subdirectory(LibraryViewer)
|
add_subdirectory(LibraryViewer)
|
||||||
add_subdirectory(Sketch3D)
|
add_subdirectory(RasterRender)
|
||||||
|
add_subdirectory(Sketch3D)
|
||||||
|
add_subdirectory(3DEditor)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,12 @@ namespace tp {
|
||||||
return hash(key);
|
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 {
|
class Map {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -223,6 +228,13 @@ namespace tp {
|
||||||
return mTable[slot]->val;
|
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) {
|
tVal& getSlotVal(ualni slot) {
|
||||||
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
DEBUG_ASSERT(slot < mNSlots && (mTable[slot] && !isDeletedNode(mTable[slot])) && "Key Error")
|
||||||
return mTable[slot]->val;
|
return mTable[slot]->val;
|
||||||
|
|
@ -242,7 +254,7 @@ namespace tp {
|
||||||
if (this == &in) {
|
if (this == &in) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ualni i = 0; i < mNSlots; i++) {
|
for (ualni i = 0; i < mNSlots; i++) {
|
||||||
if (mTable[i] && !isDeletedNode(mTable[i])) {
|
if (mTable[i] && !isDeletedNode(mTable[i])) {
|
||||||
deleteNode(mTable[i]);
|
deleteNode(mTable[i]);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
#include "EventHandler.hpp"
|
#include "EventHandler.hpp"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
EventHandler::EventHandler() = default;
|
EventHandler::EventHandler() = default;
|
||||||
|
|
@ -35,7 +33,6 @@ bool transitionsReduce[4][4] = {
|
||||||
{ true, false, true, true },
|
{ true, false, true, true },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void EventHandler::processEvent() {
|
void EventHandler::processEvent() {
|
||||||
mMutex.lock();
|
mMutex.lock();
|
||||||
auto lastEvent = mEventQueue.last();
|
auto lastEvent = mEventQueue.last();
|
||||||
|
|
@ -45,30 +42,30 @@ void EventHandler::processEvent() {
|
||||||
|
|
||||||
switch (eventData.type) {
|
switch (eventData.type) {
|
||||||
case InputEvent::Type::MOUSE_POS:
|
case InputEvent::Type::MOUSE_POS:
|
||||||
{
|
{
|
||||||
mPointer = eventData.mouseEvent;
|
mPointer = eventData.mouseEvent;
|
||||||
mEventQueue.popFront();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case InputEvent::Type::BUTTON_ACTION:
|
|
||||||
{
|
|
||||||
auto currentState = (int) mInputStates[(int) inputId].mCurrentState;
|
|
||||||
auto reportedEvent = (int) eventData.buttonAction;
|
|
||||||
|
|
||||||
mInputStates[(int) inputId].mCurrentState = transitions[currentState][reportedEvent];
|
|
||||||
|
|
||||||
if (transitionsReduce[currentState][reportedEvent]) {
|
|
||||||
mEventQueue.popFront();
|
mEventQueue.popFront();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
case InputEvent::Type::BUTTON_ACTION:
|
||||||
}
|
{
|
||||||
|
auto currentState = (int) mInputStates[(int) inputId].mCurrentState;
|
||||||
|
auto reportedEvent = (int) eventData.buttonAction;
|
||||||
|
|
||||||
|
mInputStates[(int) inputId].mCurrentState = transitions[currentState][reportedEvent];
|
||||||
|
|
||||||
|
if (transitionsReduce[currentState][reportedEvent]) {
|
||||||
|
mEventQueue.popFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
mEventQueue.popFront();
|
mEventQueue.popFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mPointerPressure = mInputStates[(int) InputID::MOUSE1].mCurrentState != InputState::State::NONE;
|
mPointerPressure = mInputStates[(int) InputID::MOUSE1].mCurrentState != InputState::State::NONE;
|
||||||
|
|
@ -78,7 +75,7 @@ void EventHandler::processEvent() {
|
||||||
|
|
||||||
const Vec2F& EventHandler::getPointer() const { return mPointer; }
|
const Vec2F& EventHandler::getPointer() const { return mPointer; }
|
||||||
|
|
||||||
bool EventHandler::isPressed(InputID id) const {
|
bool EventHandler::isPressed(InputID id) const {
|
||||||
return mInputStates[(int) id].mCurrentState == InputState::State::PRESSED;
|
return mInputStates[(int) id].mCurrentState == InputState::State::PRESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,13 +83,11 @@ bool EventHandler::isReleased(InputID id) const {
|
||||||
return mInputStates[(int) id].mCurrentState == InputState::State::RELEASED;
|
return mInputStates[(int) id].mCurrentState == InputState::State::RELEASED;
|
||||||
}
|
}
|
||||||
|
|
||||||
halnf EventHandler::getPointerPressure() const {
|
halnf EventHandler::getPointerPressure() const { return mPointerPressure; }
|
||||||
return mPointerPressure;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EventHandler::isDown(InputID id) const {
|
bool EventHandler::isDown(InputID id) const {
|
||||||
return mInputStates[(int) id].mCurrentState == InputState::State::PRESSED ||
|
return mInputStates[(int) id].mCurrentState == InputState::State::PRESSED ||
|
||||||
mInputStates[(int) id].mCurrentState == InputState::State::HOLD;
|
mInputStates[(int) id].mCurrentState == InputState::State::HOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
halnf EventHandler::getScrollY() const { return 0; }
|
halnf EventHandler::getScrollY() const { return 0; }
|
||||||
|
|
@ -62,7 +62,7 @@ namespace tp {
|
||||||
|
|
||||||
ImageHandle createImageFromTextId(ualni id, Vec2F size);
|
ImageHandle createImageFromTextId(ualni id, Vec2F size);
|
||||||
void deleteImageHandle(ImageHandle image);
|
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:
|
private:
|
||||||
Buffer<RectF> mScissors;
|
Buffer<RectF> mScissors;
|
||||||
|
|
@ -71,7 +71,9 @@ namespace tp {
|
||||||
|
|
||||||
class Graphics {
|
class Graphics {
|
||||||
public:
|
public:
|
||||||
explicit Graphics(Window* window) : mGui(window), mCanvas(window) {}
|
explicit Graphics(Window* window) :
|
||||||
|
mGui(window),
|
||||||
|
mCanvas(window) {}
|
||||||
|
|
||||||
void procBegin() {
|
void procBegin() {
|
||||||
mCanvas.procBegin();
|
mCanvas.procBegin();
|
||||||
|
|
@ -88,14 +90,12 @@ namespace tp {
|
||||||
mGui.drawBegin();
|
mGui.drawBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawEnd() {
|
void drawEnd() {
|
||||||
mCanvas.drawEnd();
|
mCanvas.drawEnd();
|
||||||
mGui.drawEnd();
|
mGui.drawEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas* getCanvas() {
|
Canvas* getCanvas() { return &mCanvas; }
|
||||||
return &mCanvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Canvas mCanvas;
|
Canvas mCanvas;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ using namespace tp;
|
||||||
|
|
||||||
class LibraryViewer : public Application {
|
class LibraryViewer : public Application {
|
||||||
public:
|
public:
|
||||||
LibraryViewer() : gui(&library, &player) {
|
LibraryViewer() :
|
||||||
|
gui(&library, &player) {
|
||||||
library.loadJson(getHome() + "Library.json");
|
library.loadJson(getHome() + "Library.json");
|
||||||
library.checkExisting();
|
library.checkExisting();
|
||||||
|
|
||||||
|
|
@ -27,22 +28,22 @@ public:
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler) override {
|
void processFrame(EventHandler* eventHandler) override {
|
||||||
auto rec = RectF{ { 0, 0 }, mWindow->getSize() };
|
auto rec = RectF{ { 0, 0 }, mWindow->getSize() };
|
||||||
|
|
||||||
|
gui.updateConfigCache(mWidgetManager);
|
||||||
gui.proc(*eventHandler, rec, rec);
|
gui.proc(*eventHandler, rec, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawFrame(Canvas* canvas) override {
|
void drawFrame(Canvas* canvas) override { gui.draw(*canvas); }
|
||||||
gui.draw(*canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Player player;
|
Player player;
|
||||||
Library library;
|
Library library;
|
||||||
|
|
||||||
|
tp::WidgetManager mWidgetManager;
|
||||||
LibraryWidget<EventHandler, Canvas> gui;
|
LibraryWidget<EventHandler, Canvas> gui;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
tp::GlobalGUIConfig config;
|
|
||||||
tp::gGlobalGUIConfig = &config;
|
|
||||||
|
|
||||||
LibraryViewer lib;
|
LibraryViewer lib;
|
||||||
lib.run();
|
lib.run();
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,10 @@ namespace tp {
|
||||||
col.mColor.setNoTransition({ 0.15f, 0.15f, 0.15f, 0.f });
|
col.mColor.setNoTransition({ 0.15f, 0.15f, 0.15f, 0.f });
|
||||||
};
|
};
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& area) override {
|
void procBody(const Events& events) override {
|
||||||
mSelected = false;
|
mSelected = false;
|
||||||
this->mArea = area;
|
|
||||||
this->mVisible = area.isOverlap(areaParent);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
if (!mTrack) return;
|
if (!mTrack) return;
|
||||||
if (!areaParent.isOverlap(area)) return;
|
if (this->mArea.isInside(events.getPointer())) {
|
||||||
if (area.isInside(events.getPointer())) {
|
|
||||||
col.set({ 0.15f, 0.15f, 0.15f, 1.f });
|
col.set({ 0.15f, 0.15f, 0.15f, 1.f });
|
||||||
mSelected = events.isReleased(InputID::MOUSE1);
|
mSelected = events.isReleased(InputID::MOUSE1);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -34,8 +29,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
if (!mTrack) return;
|
if (!mTrack) return;
|
||||||
|
|
||||||
canvas.rect(this->mArea, col.get(), 4.f);
|
canvas.rect(this->mArea, col.get(), 4.f);
|
||||||
|
|
@ -82,16 +76,7 @@ namespace tp {
|
||||||
items.append({ "Date Last Played" });
|
items.append({ "Date Last Played" });
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc(const Events&, const RectF& areaParent, const RectF& area) override {
|
void drawBody(Canvas&) override {
|
||||||
this->mArea = area;
|
|
||||||
this->mVisible = area.isOverlap(areaParent);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
if (!mTrack) return;
|
|
||||||
// renderUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Canvas&) override {
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
if (!mTrack) return;
|
if (!mTrack) return;
|
||||||
// canvas.rect(this->mArea, { 0.13f, 0.13f, 0.13f, 1.f }, 4.f);
|
// canvas.rect(this->mArea, { 0.13f, 0.13f, 0.13f, 1.f }, 4.f);
|
||||||
renderUI();
|
renderUI();
|
||||||
|
|
@ -220,11 +205,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
void procBody(const Events& events) override {
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = this->mArea.isOverlap(areaParent);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
filter();
|
filter();
|
||||||
|
|
||||||
mSplitView.proc(events, this->mArea, this->mArea);
|
mSplitView.proc(events, this->mArea, this->mArea);
|
||||||
|
|
@ -242,9 +223,7 @@ namespace tp {
|
||||||
// mCurrentTrack.proc(events, this->mArea, mSplitView.getFirst());
|
// mCurrentTrack.proc(events, this->mArea, mSplitView.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
canvas.rect(this->mArea, { 0.1f, 0.1f, 0.1f, 1.f });
|
canvas.rect(this->mArea, { 0.1f, 0.1f, 0.1f, 1.f });
|
||||||
|
|
||||||
mSplitView.draw(canvas);
|
mSplitView.draw(canvas);
|
||||||
|
|
@ -283,6 +262,14 @@ namespace tp {
|
||||||
mCurrentTrackInfo.isSongFilterChanged = false;
|
mCurrentTrackInfo.isSongFilterChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("LibraryWidget");
|
||||||
|
mSplitView.updateConfigCache(wm);
|
||||||
|
mCurrentTrack.updateConfigCache(wm);
|
||||||
|
mCurrentTrackInfo.updateConfigCache(wm);
|
||||||
|
mSongList.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Library* mLibrary = nullptr;
|
Library* mLibrary = nullptr;
|
||||||
Player* mPlayer = nullptr;
|
Player* mPlayer = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace tp {
|
||||||
|
|
||||||
Buffer<Vec3F> Points;
|
Buffer<Vec3F> Points;
|
||||||
Buffer<Vec3F> Normals;
|
Buffer<Vec3F> Normals;
|
||||||
Buffer<Vec3I> Indexes;
|
Buffer<Vec3<uhalni>> Indexes;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TopologyCache {
|
struct TopologyCache {
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
using namespace obj;
|
using namespace obj;
|
||||||
|
|
||||||
class ExampleGUI : public Application {
|
class SimpleGUI : public Application {
|
||||||
public:
|
public:
|
||||||
ExampleGUI() { gui.cd(objects_api::create<DictObject>(), "root"); }
|
SimpleGUI() { gui.cd(objects_api::create<DictObject>(), "root"); }
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler) override {}
|
void processFrame(EventHandler* eventHandler) override {}
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ int main() {
|
||||||
|
|
||||||
if (module.initialize()) {
|
if (module.initialize()) {
|
||||||
{
|
{
|
||||||
ExampleGUI gui;
|
SimpleGUI gui;
|
||||||
gui.run();
|
gui.run();
|
||||||
}
|
}
|
||||||
module.deinitialize();
|
module.deinitialize();
|
||||||
|
|
|
||||||
15
RasterRender/CMakeLists.txt
Normal file
15
RasterRender/CMakeLists.txt
Normal 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})
|
||||||
|
|
@ -5,20 +5,26 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void glerr(GLenum type) { printf("GL ERROR\n"); }
|
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;
|
using namespace tp;
|
||||||
|
|
||||||
RenderBuffer::RenderBuffer(const Vec2F& size) :
|
RenderBuffer::RenderBuffer(const Vec2F& size) :
|
||||||
mSize(size) {
|
mSize(size) {
|
||||||
|
|
||||||
mDrawBuffers[0] = {GL_COLOR_ATTACHMENT0};
|
mDrawBuffers[0] = { GL_COLOR_ATTACHMENT0 };
|
||||||
|
|
||||||
// --------- texture ---------
|
// --------- texture ---------
|
||||||
AssertGL(glGenTextures(1, &mTextureId));
|
AssertGL(glGenTextures(1, &mTextureId));
|
||||||
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
|
AssertGL(glBindTexture(GL_TEXTURE_2D, mTextureId));
|
||||||
// Give an empty image to OpenGL ( the last "0" )
|
// 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
|
// Poor filtering. Needed
|
||||||
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||||
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
AssertGL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
|
@ -26,7 +32,7 @@ RenderBuffer::RenderBuffer(const Vec2F& size) :
|
||||||
// --------- depth ---------
|
// --------- depth ---------
|
||||||
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
||||||
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, 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 ------------
|
// ------------ framebuffer ------------
|
||||||
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
||||||
|
|
@ -49,18 +55,24 @@ RenderBuffer::RenderBuffer(const Vec2F& size, tp::uint1 samples) :
|
||||||
AssertGL(glGenTextures(1, &mTextureId));
|
AssertGL(glGenTextures(1, &mTextureId));
|
||||||
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
|
AssertGL(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextureId));
|
||||||
#ifdef ENV_OS_ANDROID
|
#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
|
#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
|
#endif
|
||||||
// !?
|
// !?
|
||||||
//AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_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));
|
// AssertGL(glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||||
|
|
||||||
// ------- depth -------
|
// ------- depth -------
|
||||||
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
AssertGL(glGenRenderbuffers(1, &mDepthBufferID));
|
||||||
AssertGL(glBindRenderbuffer(GL_RENDERBUFFER, 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 -------
|
// ------- fbuff -------
|
||||||
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
AssertGL(glGenFramebuffers(1, &mFrameBufferID));
|
||||||
|
|
@ -72,9 +84,7 @@ RenderBuffer::RenderBuffer(const Vec2F& size, tp::uint1 samples) :
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint4 RenderBuffer::buffId() const {
|
uint4 RenderBuffer::buffId() const { return mFrameBufferID; }
|
||||||
return mFrameBufferID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderBuffer::beginDraw() {
|
void RenderBuffer::beginDraw() {
|
||||||
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
|
AssertGL(glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferID));
|
||||||
|
|
@ -82,7 +92,7 @@ void RenderBuffer::beginDraw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderBuffer::setViewport(const RectF& viewport) {
|
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() {
|
void RenderBuffer::clear() {
|
||||||
|
|
@ -102,9 +112,6 @@ RenderBuffer::~RenderBuffer() {
|
||||||
glDeleteRenderbuffers(1, &mDepthBufferID);
|
glDeleteRenderbuffers(1, &mDepthBufferID);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint4 RenderBuffer::texId() const {
|
uint4 RenderBuffer::texId() const { return mTextureId; }
|
||||||
return mTextureId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vec2F& RenderBuffer::getSize() const { return mSize; }
|
const Vec2F& RenderBuffer::getSize() const { return mSize; }
|
||||||
|
|
||||||
|
|
@ -13,14 +13,15 @@ namespace tp {
|
||||||
void geom_bind_source(const char* geom_src);
|
void geom_bind_source(const char* geom_src);
|
||||||
|
|
||||||
void compile();
|
void compile();
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
uint4 getu(const char* uid);
|
uint4 getu(const char* uid);
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
||||||
|
void load(const char* vert, const char* geom, const char* frag, bool paths);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
|
bool compile_shader(const char* ShaderCode, uint4 ShaderID);
|
||||||
void load(const char* vert, const char* geom, const char* frag, bool paths);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint4 programm;
|
uint4 programm;
|
||||||
|
|
@ -4,7 +4,7 @@ project(RayTracer)
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
||||||
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
|
file(GLOB HEADERS "./public/*.hpp" "./public/*/*.hpp" "./applications/*.hpp")
|
||||||
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
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)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Math Connection)
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
### -------------------------- Applications -------------------------- ###
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ extern "C" {
|
||||||
#include "lualib.h"
|
#include "lualib.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "OBJ_Loader.h"
|
#include "obj/OBJ_Loader.h"
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
@ -32,11 +32,11 @@ bool loadMeshes(tp::Scene& scene, const std::string& objetsPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
|
for (int j = 0; j < curMesh.Indices.size(); j += 3) {
|
||||||
int idx1 = (int) curMesh.Indices[j];
|
auto idx1 = (uhalni) curMesh.Indices[j];
|
||||||
int idx2 = (int) curMesh.Indices[j + 1];
|
auto idx2 = (uhalni) curMesh.Indices[j + 1];
|
||||||
int idx3 = (int) curMesh.Indices[j + 2];
|
auto idx3 = (uhalni) curMesh.Indices[j + 2];
|
||||||
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
|
// printf("{ %i, %i, %i },\n", idx1, idx2, idx3);
|
||||||
object->mTopology.Indexes.append(Vec3I{ idx1, idx2, idx3 });
|
object->mTopology.Indexes.append(Vec3<uhalni>{ idx1, idx2, idx3 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
|
if (object->mTopology.Normals.size() != object->mTopology.Points.size()) {
|
||||||
|
|
@ -139,7 +139,6 @@ void loadScene(tp::Scene& scene, const std::string& scenePath, tp::RayTracer::Re
|
||||||
// Remove the filename from the path
|
// Remove the filename from the path
|
||||||
fs::path directoryPath = fullPath.remove_filename();
|
fs::path directoryPath = fullPath.remove_filename();
|
||||||
|
|
||||||
|
|
||||||
if (luaL_dofile(L, scenePath.c_str()) != 0) {
|
if (luaL_dofile(L, scenePath.c_str()) != 0) {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
printf("Cant open scene script.\n");
|
printf("Cant open scene script.\n");
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
project(Sketch3D)
|
project(Sketch3D)
|
||||||
|
|
||||||
### ---------------------- Externals --------------------- ###
|
### ---------------------- Externals --------------------- ###
|
||||||
set(BINDINGS_INCLUDE ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
|
set(BINDINGS_INCLUDE ../Externals/glfw/include)
|
||||||
set(BINDINGS_LIBS glfw Imgui ${GLEW_LIB})
|
set(BINDINGS_LIBS glfw Imgui)
|
||||||
|
|
||||||
### ---------------------- Static Library --------------------- ###
|
### ---------------------- Static Library --------------------- ###
|
||||||
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
|
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})
|
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ${BINDINGS_INCLUDE} ./ext/)
|
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})
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${BINDINGS_LIBS})
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
### -------------------------- Applications -------------------------- ###
|
||||||
add_executable(Sketch3DApp ./applications/Entry.cpp)
|
add_executable(Sketch3DApp ./applications/Entry.cpp)
|
||||||
target_link_libraries(Sketch3DApp ${PROJECT_NAME})
|
target_link_libraries(Sketch3DApp ${PROJECT_NAME})
|
||||||
|
|
||||||
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "rsc" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
file(COPY "applications/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
file(COPY "applications/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
|
|
||||||
|
|
@ -8,30 +8,25 @@ using namespace tp;
|
||||||
|
|
||||||
class Sketch3DApplication : public Application {
|
class Sketch3DApplication : public Application {
|
||||||
public:
|
public:
|
||||||
Sketch3DApplication() : mGui(*mGraphics->getCanvas(), {1920, 1080}) {}
|
Sketch3DApplication() :
|
||||||
|
mGui(*mGraphics->getCanvas(), { 1920, 1080 }) {}
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler) override {
|
void processFrame(EventHandler* eventHandler) override {
|
||||||
auto rec = RectF( { 0, 0 }, mWindow->getSize() );
|
auto rec = RectF({ 0, 0 }, mWindow->getSize());
|
||||||
|
mGui.updateConfigCache(mWidgetManager);
|
||||||
mGui.proc(*eventHandler, rec, rec);
|
mGui.proc(*eventHandler, rec, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawFrame(Canvas* canvas) override {
|
void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); }
|
||||||
mGui.draw(*canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WidgetManager mWidgetManager;
|
||||||
Sketch3DGUI<EventHandler, Canvas> mGui;
|
Sketch3DGUI<EventHandler, Canvas> mGui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void runApp() {
|
void runApp() {
|
||||||
tp::GlobalGUIConfig config;
|
|
||||||
tp::gGlobalGUIConfig = &config;
|
|
||||||
|
|
||||||
Sketch3DApplication app;
|
Sketch3DApplication app;
|
||||||
app.run();
|
app.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() { runApp(); }
|
||||||
runApp();
|
|
||||||
}
|
|
||||||
|
|
@ -9,16 +9,14 @@ namespace tp {
|
||||||
class Sketch3DWidget : public Widget<Events, Canvas> {
|
class Sketch3DWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
Sketch3DWidget(Canvas& canvas, Vec2F renderResolution) :
|
Sketch3DWidget(Canvas& canvas, Vec2F renderResolution) :
|
||||||
mRenderer(renderResolution) {
|
mRenderer(renderResolution) {
|
||||||
mImage = canvas.createImageFromTextId(mRenderer.getBuff()->texId(), mRenderer.getBuff()->getSize());
|
mImage = canvas.createImageFromTextId(mRenderer.getBuff()->texId(), mRenderer.getBuff()->getSize());
|
||||||
mCanvas = &canvas;
|
mCanvas = &canvas;
|
||||||
|
|
||||||
mProject.mBackgroundColor = { 0.13f, 0.13f, 0.13f, 1.f };
|
mProject.mBackgroundColor = { 0.13f, 0.13f, 0.13f, 1.f };
|
||||||
}
|
}
|
||||||
|
|
||||||
~Sketch3DWidget() {
|
~Sketch3DWidget() { mCanvas->deleteImageHandle(mImage); }
|
||||||
mCanvas->deleteImageHandle(mImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& area) override {
|
void proc(const Events& events, const RectF& areaParent, const RectF& area) override {
|
||||||
|
|
||||||
|
|
@ -51,20 +49,24 @@ namespace tp {
|
||||||
mProject.mCamera.setRatio(this->mArea.w / this->mArea.z);
|
mProject.mCamera.setRatio(this->mArea.w / this->mArea.z);
|
||||||
|
|
||||||
switch (mMode) {
|
switch (mMode) {
|
||||||
case Mode::MOVE: {
|
case Mode::MOVE:
|
||||||
|
{
|
||||||
if (mAction) mProject.mCamera.move(relativePos, relativePosPrev);
|
if (mAction) mProject.mCamera.move(relativePos, relativePosPrev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Mode::ZOOM: {
|
case Mode::ZOOM:
|
||||||
|
{
|
||||||
halnf factor = absolutePos.y / mActionPosAbsolutePrev.y;
|
halnf factor = absolutePos.y / mActionPosAbsolutePrev.y;
|
||||||
if (mAction) mProject.mCamera.zoom(factor);
|
if (mAction) mProject.mCamera.zoom(factor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Mode::ROTATE: {
|
case Mode::ROTATE:
|
||||||
|
{
|
||||||
if (mAction) mProject.mCamera.rotate(-relativeDelta.x * halnf(PI), -relativeDelta.y * halnf(PI));
|
if (mAction) mProject.mCamera.rotate(-relativeDelta.x * halnf(PI), -relativeDelta.y * halnf(PI));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Mode::DRAW: {
|
case Mode::DRAW:
|
||||||
|
{
|
||||||
mProject.sample(events.getPointerPressure(), this->mArea.w / this->mArea.z, crs);
|
mProject.sample(events.getPointerPressure(), this->mArea.w / this->mArea.z, crs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -74,20 +76,15 @@ namespace tp {
|
||||||
mActionPosAbsolutePrev = absolutePos;
|
mActionPosAbsolutePrev = absolutePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
mRenderer.renderToTexture(&mProject, this->mArea.size);
|
mRenderer.renderToTexture(&mProject, this->mArea.size);
|
||||||
canvas.drawImage(this->mArea, &mImage, 0, 1, 12);
|
canvas.drawImage(this->mArea, &mImage, 0, 1, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColor(const RGBA& color) {
|
void setColor(const RGBA& color) { ((PencilBrush*) mProject.mBrushes.get("pencil"))->mCol = color; }
|
||||||
((PencilBrush*) mProject.mBrushes.get("pencil"))->mCol = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Mode {
|
enum class Mode { MOVE, ROTATE, ZOOM, DRAW, NONE } mMode = Mode::NONE;
|
||||||
MOVE, ROTATE, ZOOM, DRAW, NONE
|
|
||||||
} mMode = Mode::NONE;
|
|
||||||
|
|
||||||
Vec2F mActionPosAbsolutePrev = { 0, 0 };
|
Vec2F mActionPosAbsolutePrev = { 0, 0 };
|
||||||
bool mAction = false;
|
bool mAction = false;
|
||||||
|
|
@ -102,12 +99,8 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class Sketch3DGUI : public Widget<Events, Canvas> {
|
class Sketch3DGUI : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
Sketch3DGUI(Canvas& canvas, Vec2F renderResolution) : mViewport(canvas, renderResolution) {
|
Sketch3DGUI(Canvas& canvas, Vec2F renderResolution) :
|
||||||
this->createConfig("Sketch3D");
|
mViewport(canvas, renderResolution) {
|
||||||
|
|
||||||
this->addColor("Background", "Background");
|
|
||||||
this->addValue("Rounding", "Rounding");
|
|
||||||
|
|
||||||
mDrawButton = new ButtonWidget<Events, Canvas>("Draw", { 0, 0, 100, 30 });
|
mDrawButton = new ButtonWidget<Events, Canvas>("Draw", { 0, 0, 100, 30 });
|
||||||
mMoveButton = new ButtonWidget<Events, Canvas>("Pan View", { 0, 0, 100, 30 });
|
mMoveButton = new ButtonWidget<Events, Canvas>("Pan View", { 0, 0, 100, 30 });
|
||||||
mRotateButton = new ButtonWidget<Events, Canvas>("Rotate view", { 0, 0, 100, 30 });
|
mRotateButton = new ButtonWidget<Events, Canvas>("Rotate view", { 0, 0, 100, 30 });
|
||||||
|
|
@ -119,26 +112,22 @@ namespace tp {
|
||||||
mOptions.mContents.append(mZoomButton);
|
mOptions.mContents.append(mZoomButton);
|
||||||
|
|
||||||
// add color sliders
|
// add color sliders
|
||||||
mRed = new NamedSliderWidget < Events, Canvas >("Red");
|
mRed = new NamedSliderWidget<Events, Canvas>("Red");
|
||||||
mGreen = new NamedSliderWidget < Events, Canvas >("Green");
|
mGreen = new NamedSliderWidget<Events, Canvas>("Green");
|
||||||
mBlue = new NamedSliderWidget < Events, Canvas >("Blue");
|
mBlue = new NamedSliderWidget<Events, Canvas>("Blue");
|
||||||
|
|
||||||
mOptions.mContents.append(mRed);
|
mOptions.mContents.append(mRed);
|
||||||
mOptions.mContents.append(mGreen);
|
mOptions.mContents.append(mGreen);
|
||||||
mOptions.mContents.append(mBlue);
|
mOptions.mContents.append(mBlue);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Sketch3DGUI() {
|
~Sketch3DGUI() {
|
||||||
for (auto item : mOptions.mContents) {
|
for (auto item : mOptions.mContents) {
|
||||||
delete item.data();
|
delete item.data();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& area) override {
|
void procBody(const Events& events) override {
|
||||||
this->mArea = area;
|
|
||||||
this->mVisible = area.isOverlap(areaParent);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
mSplitView.proc(events, this->mArea, this->mArea);
|
mSplitView.proc(events, this->mArea, this->mArea);
|
||||||
mViewport.proc(events, this->mArea, mSplitView.getFirst());
|
mViewport.proc(events, this->mArea, mSplitView.getFirst());
|
||||||
mOptions.proc(events, this->mArea, mSplitView.getSecond());
|
mOptions.proc(events, this->mArea, mSplitView.getSecond());
|
||||||
|
|
@ -156,16 +145,25 @@ namespace tp {
|
||||||
mViewport.setColor(RGBA(mRed->mSlider.mFactor, mGreen->mSlider.mFactor, mBlue->mSlider.mFactor, 1.f));
|
mViewport.setColor(RGBA(mRed->mSlider.mFactor, mGreen->mSlider.mFactor, mBlue->mSlider.mFactor, 1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
canvas.rect(this->mArea, mBackgroundColor, mRounding);
|
||||||
|
|
||||||
canvas.rect(this->mArea, this->getColor("Background"), this->getValue("Rounding"));
|
|
||||||
|
|
||||||
mSplitView.draw(canvas);
|
mSplitView.draw(canvas);
|
||||||
mViewport.draw(canvas);
|
mViewport.draw(canvas);
|
||||||
mOptions.draw(canvas);
|
mOptions.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("Sketch3DGui");
|
||||||
|
|
||||||
|
mBackgroundColor = wm.getColor("Background", "Background");
|
||||||
|
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||||
|
|
||||||
|
mSplitView.updateConfigCache(wm);
|
||||||
|
mOptions.updateConfigCache(wm);
|
||||||
|
mViewport.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Sketch3DWidget<Events, Canvas> mViewport;
|
Sketch3DWidget<Events, Canvas> mViewport;
|
||||||
SplitView<Events, Canvas> mSplitView;
|
SplitView<Events, Canvas> mSplitView;
|
||||||
|
|
@ -179,5 +177,8 @@ namespace tp {
|
||||||
NamedSliderWidget<Events, Canvas>* mRed = nullptr;
|
NamedSliderWidget<Events, Canvas>* mRed = nullptr;
|
||||||
NamedSliderWidget<Events, Canvas>* mGreen = nullptr;
|
NamedSliderWidget<Events, Canvas>* mGreen = nullptr;
|
||||||
NamedSliderWidget<Events, Canvas>* mBlue = nullptr;
|
NamedSliderWidget<Events, Canvas>* mBlue = nullptr;
|
||||||
|
|
||||||
|
RGBA mBackgroundColor;
|
||||||
|
halnf mRounding = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,12 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
|
||||||
|
|
||||||
### -------------------------- Applications -------------------------- ###
|
### -------------------------- Applications -------------------------- ###
|
||||||
|
|
||||||
add_executable(ExampleGui examples/Entry.cpp)
|
add_executable(SimpleGui examples/SimpleGUI.cpp)
|
||||||
target_link_libraries(ExampleGui ${PROJECT_NAME} ${GLEW_LIB})
|
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
|
||||||
target_include_directories(ExampleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
|
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}/")
|
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
#include "ExampleGUI.hpp"
|
#include "ChatGUI.hpp"
|
||||||
|
|
||||||
#include "GraphicApplication.hpp"
|
#include "GraphicApplication.hpp"
|
||||||
|
|
||||||
|
|
@ -9,23 +9,22 @@ class ExampleGUI : public Application {
|
||||||
public:
|
public:
|
||||||
ExampleGUI() = default;
|
ExampleGUI() = default;
|
||||||
|
|
||||||
void processFrame(EventHandler* eventHandler) override {
|
void processFrame(EventHandler* eventHandler) override {
|
||||||
auto rec = RectF( { 0, 0 }, mWindow->getSize() );
|
auto rec = RectF({ 0, 0 }, mWindow->getSize());
|
||||||
|
|
||||||
|
mGui.updateConfigCache(mWidgetManager);
|
||||||
|
|
||||||
mGui.proc(*eventHandler, rec, rec);
|
mGui.proc(*eventHandler, rec, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawFrame(Canvas* canvas) override {
|
void drawFrame(Canvas* canvas) override { mGui.draw(*canvas); }
|
||||||
mGui.draw(*canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WidgetManager mWidgetManager;
|
||||||
ComplexWidget<EventHandler, Canvas> mGui;
|
ComplexWidget<EventHandler, Canvas> mGui;
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
GlobalGUIConfig mConfig;
|
|
||||||
gGlobalGUIConfig = &mConfig;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ExampleGUI gui;
|
ExampleGUI gui;
|
||||||
gui.run();
|
gui.run();
|
||||||
|
|
@ -7,15 +7,7 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class UserWidget : public Widget<Events, Canvas> {
|
class UserWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
UserWidget() {
|
UserWidget() = default;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
|
|
@ -28,34 +20,40 @@ namespace tp {
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
if (!this->mVisible) return;
|
||||||
|
|
||||||
if (mIsHover) canvas.rect(this->mArea, this->getColor("Accent"), this->getValue("Rounding"));
|
if (mIsHover) canvas.rect(this->mArea, mAccentColor, mRounding);
|
||||||
else canvas.rect(this->mArea, this->getColor("Base"), this->getValue("Rounding"));
|
else canvas.rect(this->mArea, mBaseColor, mRounding);
|
||||||
|
|
||||||
const auto padding = this->getValue("Padding");
|
canvas.text(mUser.c_str(), this->mArea, mFontSize, Canvas::CC, mPadding, mUserColor);
|
||||||
const auto size = this->getValue("Size");
|
}
|
||||||
const auto colUser = this->getColor("ColUser");
|
|
||||||
|
|
||||||
canvas.text(mUser.c_str(), this->mArea, size, Canvas::CC, padding, colUser);
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("UserWidget");
|
||||||
|
|
||||||
|
mBaseColor = wm.getColor("Base", "Base");
|
||||||
|
mFontSize = wm.getNumber("Size", "FontSize");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
mUserColor = wm.getColor("ColUser", "Front");
|
||||||
|
mAccentColor = wm.getColor("Accent", "Accent");
|
||||||
|
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string mUser = "UserName";
|
std::string mUser = "UserName";
|
||||||
bool mIsHover = false;
|
bool mIsHover = false;
|
||||||
|
|
||||||
|
RGBA mBaseColor;
|
||||||
|
RGBA mUserColor;
|
||||||
|
RGBA mAccentColor;
|
||||||
|
halnf mPadding = 0;
|
||||||
|
halnf mFontSize = 0;
|
||||||
|
halnf mRounding = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class MessageWidget : public Widget<Events, Canvas> {
|
class MessageWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
MessageWidget() {
|
MessageWidget() = default;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
|
|
@ -67,14 +65,7 @@ namespace tp {
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
if (!this->mVisible) return;
|
||||||
|
if (mIsHover) canvas.rect(this->mArea, mBaseColor, mRounding);
|
||||||
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");
|
|
||||||
|
|
||||||
auto userName = this->mArea;
|
auto userName = this->mArea;
|
||||||
userName.w = 25;
|
userName.w = 25;
|
||||||
|
|
@ -83,22 +74,40 @@ namespace tp {
|
||||||
content.y = userName.y + userName.w;
|
content.y = userName.y + userName.w;
|
||||||
content.w = this->mArea.w - userName.w;
|
content.w = this->mArea.w - userName.w;
|
||||||
|
|
||||||
canvas.text(mContent.c_str(), content, size, Canvas::LC, padding, col);
|
canvas.text(mContent.c_str(), content, mFontSize, Canvas::LC, mPadding, mUserColorDim);
|
||||||
canvas.text(mUser.c_str(), userName, sizeUser, Canvas::LC, padding, colUser);
|
canvas.text(mUser.c_str(), userName, mFontSizeDim, Canvas::LC, mPadding, mUserColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("MessageWidget");
|
||||||
|
|
||||||
|
mBaseColor = wm.getColor("Base", "Base");
|
||||||
|
mFontSize = wm.getNumber("Size", "FontSize");
|
||||||
|
mFontSizeDim = wm.getNumber("SizeUser", "FontSizeDim");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
mUserColor = wm.getColor("UserColor", "Front");
|
||||||
|
mUserColorDim = wm.getColor("UserColorDim", "FrontDim");
|
||||||
|
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string mContent = "Message Content";
|
std::string mContent = "Message Content";
|
||||||
std::string mUser = "UserName";
|
std::string mUser = "UserName";
|
||||||
bool mIsHover = false;
|
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>
|
template <typename Events, typename Canvas>
|
||||||
class LoginWidget : public Widget<Events, Canvas> {
|
class LoginWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
explicit LoginWidget() {
|
explicit LoginWidget() {
|
||||||
this->createConfig("Login");
|
|
||||||
this->addColor("Back", "Background");
|
|
||||||
mPass.mId = "pass";
|
mPass.mId = "pass";
|
||||||
mUser.mId = "user";
|
mUser.mId = "user";
|
||||||
mButton.mLabel.mLabel = "Login";
|
mButton.mLabel.mLabel = "Login";
|
||||||
|
|
@ -120,26 +129,36 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
canvas.rect(this->mArea, this->getColor("Back"));
|
canvas.rect(this->mArea, mBGColor);
|
||||||
mButton.draw(canvas);
|
mButton.draw(canvas);
|
||||||
mUser.draw(canvas);
|
mUser.draw(canvas);
|
||||||
mPass.draw(canvas);
|
mPass.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("LoginWidget");
|
||||||
|
|
||||||
|
mBGColor = wm.getColor("Back", "Base");
|
||||||
|
|
||||||
|
mUser.updateConfigCache(wm);
|
||||||
|
mPass.updateConfigCache(wm);
|
||||||
|
mButton.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextInputWidget<Events, Canvas> mUser;
|
TextInputWidget<Events, Canvas> mUser;
|
||||||
TextInputWidget<Events, Canvas> mPass;
|
TextInputWidget<Events, Canvas> mPass;
|
||||||
ButtonWidget<Events, Canvas> mButton;
|
ButtonWidget<Events, Canvas> mButton;
|
||||||
bool mLogged = false;
|
bool mLogged = false;
|
||||||
|
|
||||||
|
RGBA mBGColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class ActiveChatWidget : public Widget<Events, Canvas> {
|
class ActiveChatWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ActiveChatWidget() {
|
ActiveChatWidget() {
|
||||||
this->createConfig("ActiveChat");
|
|
||||||
this->addColor("Back", "Background");
|
|
||||||
this->addValue("Padding", "Padding");
|
|
||||||
mSend.mLabel.mLabel = "Send";
|
mSend.mLabel.mLabel = "Send";
|
||||||
mMessage.mId = "Message";
|
mMessage.mId = "Message";
|
||||||
}
|
}
|
||||||
|
|
@ -152,16 +171,16 @@ namespace tp {
|
||||||
|
|
||||||
auto input = this->mArea;
|
auto input = this->mArea;
|
||||||
input.y = history.w + 10;
|
input.y = history.w + 10;
|
||||||
input.w = 40 - this->getValue("Padding");
|
input.w = 40 - mPadding;
|
||||||
input.x += this->getValue("Padding");
|
input.x += mPadding;
|
||||||
input.z -= this->getValue("Padding");
|
input.z -= mPadding;
|
||||||
|
|
||||||
auto inputMessage = input;
|
auto inputMessage = input;
|
||||||
inputMessage.z -= 100;
|
inputMessage.z -= 100;
|
||||||
|
|
||||||
auto inputSend = input;
|
auto inputSend = input;
|
||||||
inputSend.x = inputMessage.x + inputMessage.z + this->getValue("Padding");
|
inputSend.x = inputMessage.x + inputMessage.z + mPadding;
|
||||||
inputSend.z = 100 - this->getValue("Padding") * 2;
|
inputSend.z = 100 - mPadding * 2;
|
||||||
|
|
||||||
mSend.proc(events, this->mArea, inputSend);
|
mSend.proc(events, this->mArea, inputSend);
|
||||||
mMessage.proc(events, this->mArea, inputMessage);
|
mMessage.proc(events, this->mArea, inputMessage);
|
||||||
|
|
@ -174,27 +193,41 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
canvas.rect(this->mArea, this->getColor("Back"));
|
canvas.rect(this->mArea, mBGColor);
|
||||||
mHistoryView.draw(canvas);
|
mHistoryView.draw(canvas);
|
||||||
mMessage.draw(canvas);
|
mMessage.draw(canvas);
|
||||||
mSend.draw(canvas);
|
mSend.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("ActiveChat");
|
||||||
|
|
||||||
|
mBGColor = wm.getColor("Back", "Background");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
|
||||||
|
mHistoryView.updateConfigCache(wm);
|
||||||
|
mMessage.updateConfigCache(wm);
|
||||||
|
mSend.updateConfigCache(wm);
|
||||||
|
|
||||||
|
for (auto message : mMessages) {
|
||||||
|
message->updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer<MessageWidget<Events, Canvas>> mMessages;
|
Buffer<MessageWidget<Events, Canvas>> mMessages;
|
||||||
ScrollableWindow<Events, Canvas> mHistoryView;
|
ScrollableWindow<Events, Canvas> mHistoryView;
|
||||||
TextInputWidget<Events, Canvas> mMessage;
|
TextInputWidget<Events, Canvas> mMessage;
|
||||||
ButtonWidget<Events, Canvas> mSend;
|
ButtonWidget<Events, Canvas> mSend;
|
||||||
|
|
||||||
|
RGBA mBGColor;
|
||||||
|
halnf mPadding = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class ChattingWidget : public Widget<Events, Canvas> {
|
class ChattingWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ChattingWidget() {
|
ChattingWidget() {
|
||||||
this->createConfig("Chatting");
|
|
||||||
this->addColor("Back", "Background");
|
|
||||||
this->addValue("Padding", "Padding");
|
|
||||||
|
|
||||||
// todo : fetch code
|
// todo : fetch code
|
||||||
mUsers.append(UserWidget<Events, Canvas>());
|
mUsers.append(UserWidget<Events, Canvas>());
|
||||||
mUsers.append(UserWidget<Events, Canvas>());
|
mUsers.append(UserWidget<Events, Canvas>());
|
||||||
|
|
@ -225,34 +258,44 @@ namespace tp {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
|
|
||||||
mSplitView.proc(events, aArea, aArea);
|
mSplitView.proc(events, aArea, aArea);
|
||||||
|
|
||||||
const auto padding = this->getValue("Padding");
|
|
||||||
mSideView.proc(events, this->mArea, mSplitView.getSecond());
|
mSideView.proc(events, this->mArea, mSplitView.getSecond());
|
||||||
|
|
||||||
mActive.proc(events, aArea, mSplitView.getFirst());
|
mActive.proc(events, aArea, mSplitView.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
canvas.rect(this->mArea, this->getColor("Back"));
|
canvas.rect(this->mArea, mBGColor);
|
||||||
mSplitView.draw(canvas);
|
mSplitView.draw(canvas);
|
||||||
mSideView.draw(canvas);
|
mSideView.draw(canvas);
|
||||||
mActive.draw(canvas);
|
mActive.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("ChattingWidget");
|
||||||
|
|
||||||
|
mBGColor = wm.getColor("Back", "Background");
|
||||||
|
|
||||||
|
mSideView.updateConfigCache(wm);
|
||||||
|
mActive.updateConfigCache(wm);
|
||||||
|
mSplitView.updateConfigCache(wm);
|
||||||
|
|
||||||
|
for (auto user : mUsers) {
|
||||||
|
user->updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Buffer<UserWidget<Events, Canvas>> mUsers;
|
Buffer<UserWidget<Events, Canvas>> mUsers;
|
||||||
ScrollableWindow<Events, Canvas> mSideView;
|
ScrollableWindow<Events, Canvas> mSideView;
|
||||||
ActiveChatWidget<Events, Canvas> mActive;
|
ActiveChatWidget<Events, Canvas> mActive;
|
||||||
SplitView<Events, Canvas> mSplitView;
|
SplitView<Events, Canvas> mSplitView;
|
||||||
|
|
||||||
|
RGBA mBGColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class ComplexWidget : public Widget<Events, Canvas> {
|
class ComplexWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ComplexWidget() {
|
ComplexWidget() = default;
|
||||||
this->createConfig("chat");
|
|
||||||
this->addColor("Back", "Background");
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
void proc(const Events& events, const RectF& areaParent, const RectF& aArea) override {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
|
|
@ -268,14 +311,25 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void draw(Canvas& canvas) override {
|
||||||
canvas.rect(this->mArea, this->getColor("Back"));
|
canvas.rect(this->mArea, mBGColor);
|
||||||
if (mLogged) mChatting.draw(canvas);
|
if (mLogged) mChatting.draw(canvas);
|
||||||
else mLogin.draw(canvas);
|
else mLogin.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("ChatGui");
|
||||||
|
|
||||||
|
mBGColor = wm.getColor("Back", "Background");
|
||||||
|
|
||||||
|
mLogin.updateConfigCache(wm);
|
||||||
|
mChatting.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mLogged = false;
|
bool mLogged = false;
|
||||||
LoginWidget<Events, Canvas> mLogin;
|
LoginWidget<Events, Canvas> mLogin;
|
||||||
ChattingWidget<Events, Canvas> mChatting;
|
ChattingWidget<Events, Canvas> mChatting;
|
||||||
|
|
||||||
|
RGBA mBGColor;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
44
Widgets/examples/SimpleGUI.cpp
Normal file
44
Widgets/examples/SimpleGUI.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
#include "ChatGUI.hpp"
|
||||||
|
|
||||||
|
#include "GraphicApplication.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
class SimpleGUI : public Application {
|
||||||
|
public:
|
||||||
|
SimpleGUI() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,4 @@
|
||||||
|
|
||||||
#include "Graphics.hpp"
|
#include "Graphics.hpp"
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {}
|
||||||
GlobalGUIConfig* gGlobalGUIConfig = nullptr;
|
|
||||||
}
|
|
||||||
|
|
@ -7,40 +7,15 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class ButtonWidget : public Widget<Events, Canvas> {
|
class ButtonWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ButtonWidget() {
|
ButtonWidget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
this->mLabel.mLabel = label;
|
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 {
|
void procBody(const Events& events) {
|
||||||
this->mArea = aArea;
|
mIsHover = this->mArea.isInside(events.getPointer());
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
mIsHover = false;
|
|
||||||
|
|
||||||
if (!areaParent.isOverlap(aArea)) {
|
|
||||||
mIsReleased = false;
|
|
||||||
mIsPressed = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsHover = aArea.isInside(events.getPointer());
|
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||||
mIsPressed = true;
|
mIsPressed = true;
|
||||||
|
|
@ -53,26 +28,46 @@ namespace tp {
|
||||||
|
|
||||||
if (!mIsHover) mIsPressed = false;
|
if (!mIsHover) mIsPressed = false;
|
||||||
|
|
||||||
mLabel.proc(events, aArea, aArea);
|
mLabel.proc(events, this->mArea, this->mArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
if (mIsPressed) {
|
if (mIsPressed) {
|
||||||
canvas.rect(this->mArea, this->getColor("Pressed"), this->getValue("Rounding"));
|
canvas.rect(this->mArea, pressedColor, rounding);
|
||||||
} else if (mIsHover) {
|
} else if (mIsHover) {
|
||||||
canvas.rect(this->mArea, this->getColor("Hovered"), this->getValue("Rounding"));
|
canvas.rect(this->mArea, hoveredColor, rounding);
|
||||||
} else {
|
} else {
|
||||||
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
|
canvas.rect(this->mArea, accentColor, rounding);
|
||||||
}
|
}
|
||||||
mLabel.draw(canvas);
|
mLabel.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("Button");
|
||||||
|
|
||||||
|
pressedColor = wm.getColor("Pressed", "Action");
|
||||||
|
hoveredColor = wm.getColor("Hovered", "Interaction");
|
||||||
|
accentColor = wm.getColor("Default", "Accent");
|
||||||
|
rounding = wm.getNumber("Rounding", "Rounding");
|
||||||
|
|
||||||
|
// mPressEvent = wm.getEventState("Activate", { { InputID::MOUSE1, InputState::PRESSED } });
|
||||||
|
|
||||||
|
mLabel.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LabelWidget<Events, Canvas> mLabel;
|
LabelWidget<Events, Canvas> mLabel;
|
||||||
|
|
||||||
bool mIsHover = false;
|
bool mIsHover = false;
|
||||||
bool mIsPressed = false;
|
bool mIsPressed = false;
|
||||||
bool mIsReleased = false;
|
bool mIsReleased = false;
|
||||||
|
|
||||||
|
RGBA pressedColor;
|
||||||
|
RGBA hoveredColor;
|
||||||
|
RGBA accentColor;
|
||||||
|
halnf rounding = 0;
|
||||||
|
|
||||||
|
InputState mPressEvent;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -6,33 +6,26 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class LabelWidget : public Widget<Events, Canvas> {
|
class LabelWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
LabelWidget() {
|
LabelWidget() = default;
|
||||||
this->createConfig("Label");
|
|
||||||
this->addValue("Size", "FontSize");
|
void drawBody(Canvas& canvas) override {
|
||||||
this->addValue("Padding", "Padding");
|
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor);
|
||||||
this->addColor("Default", "Front");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
public:
|
||||||
this->mArea = aArea;
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
wm.setActiveId("Label");
|
||||||
if (!this->mVisible) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
fontSize = wm.getNumber("Size", "FontSize");
|
||||||
if (!this->mVisible) return;
|
padding = wm.getNumber("Padding", "Padding");
|
||||||
|
fontColor = wm.getColor("Default", "Front");
|
||||||
canvas.text(
|
|
||||||
mLabel.c_str(),
|
|
||||||
this->mArea,
|
|
||||||
this->getValue("Size"),
|
|
||||||
Canvas::CC,
|
|
||||||
this->getValue("Padding"),
|
|
||||||
this->getColor("Default")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string mLabel = "Label";
|
std::string mLabel = "Label";
|
||||||
|
|
||||||
|
halnf fontSize = 10;
|
||||||
|
halnf padding = 0;
|
||||||
|
RGBA fontColor = { 1, 1, 1, 1 };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -8,17 +8,7 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class ScrollBarWidget : public Widget<Events, Canvas> {
|
class ScrollBarWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ScrollBarWidget() {
|
ScrollBarWidget() = default;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
// takes whole area
|
// takes whole area
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
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 (mSizeFraction > 1.f) return;
|
||||||
// if (!areaParent.isOverlap(getHandle())) return;
|
// if (!areaParent.isOverlap(getHandle())) return;
|
||||||
|
|
||||||
tp::RGBA col = this->getColor("Handle");
|
tp::RGBA col = mHandleColor;
|
||||||
|
|
||||||
if (mIsScrolling) {
|
if (mIsScrolling) {
|
||||||
col = this->getColor("Scrolling");
|
col = mScrollingColor;
|
||||||
} else if (mHovered) {
|
} 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 {
|
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 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;
|
auto diffSize = sliderSize - area.w * mSizeFraction;
|
||||||
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
|
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
|
||||||
}
|
}
|
||||||
|
|
@ -109,14 +93,28 @@ namespace tp {
|
||||||
if (mSizeFraction > 1.f) {
|
if (mSizeFraction > 1.f) {
|
||||||
return this->mArea;
|
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 {
|
RectF getHandle() const {
|
||||||
return { this->mArea.x + this->mArea.z - this->getValue("HandleSize") + this->getValue("Padding"),
|
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
|
||||||
this->mArea.y + this->getValue("Padding"),
|
this->mArea.y + mPadding,
|
||||||
this->getValue("HandleSize") - this->getValue("Padding") * 2,
|
mHandleSize - mPadding * 2,
|
||||||
this->mArea.w - this->getValue("Padding") * 2 };
|
this->mArea.w - mPadding * 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("Scrollbar");
|
||||||
|
|
||||||
|
mDefaultColor = wm.getColor("Default", "Base");
|
||||||
|
mHandleColor = wm.getColor("Handle", "Accent");
|
||||||
|
mHoveredColor = wm.getColor("Hovered", "Interaction");
|
||||||
|
mScrollingColor = wm.getColor("Scrolling", "Action");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
mHandleSize = wm.getNumber("HandleSize", 20.f);
|
||||||
|
mMinSize = wm.getNumber("MinSize", 20.f);
|
||||||
|
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -126,29 +124,29 @@ namespace tp {
|
||||||
halnf mSizeFraction = 1.f;
|
halnf mSizeFraction = 1.f;
|
||||||
halnf mPositionFraction = 0.f;
|
halnf mPositionFraction = 0.f;
|
||||||
bool mHovered = false;
|
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>
|
template <typename Events, typename Canvas>
|
||||||
class ScrollableWindow : public Widget<Events, Canvas> {
|
class ScrollableWindow : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
ScrollableWindow() {
|
ScrollableWindow() = default;
|
||||||
this->createConfig("ScrollableWindow");
|
|
||||||
this->addColor("Default", "Base");
|
|
||||||
this->addValue("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
||||||
~ScrollableWindow() = default;
|
~ScrollableWindow() = default;
|
||||||
|
|
||||||
// takes whole area
|
// takes whole area
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
void procBody(const Events& events) override {
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
updateContents();
|
updateContents();
|
||||||
updateContentSize();
|
updateContentSize();
|
||||||
|
|
||||||
const auto padding = this->getValue("Padding");
|
const auto padding = mPadding;
|
||||||
|
|
||||||
mScroller.mSizeFraction = this->mArea.w / mContentSize;
|
mScroller.mSizeFraction = this->mArea.w / mContentSize;
|
||||||
mScroller.proc(events, this->mArea, this->mArea);
|
mScroller.proc(events, this->mArea, this->mArea);
|
||||||
|
|
@ -168,9 +166,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
mScroller.draw(canvas);
|
mScroller.draw(canvas);
|
||||||
|
|
||||||
canvas.pushClamp(this->mArea);
|
canvas.pushClamp(this->mArea);
|
||||||
|
|
@ -180,16 +176,29 @@ namespace tp {
|
||||||
canvas.popClamp();
|
canvas.popClamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("ScrollableWidget");
|
||||||
|
|
||||||
|
mDefaultColor = wm.getColor("Default", "Base");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
|
||||||
|
mScroller.updateConfigCache(wm);
|
||||||
|
|
||||||
|
for (auto item : mContents) {
|
||||||
|
item->updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateContents() {
|
void updateContents() {
|
||||||
if (mContents.size()) {
|
if (mContents.size()) {
|
||||||
const auto padding = this->getValue("Padding");
|
const halnf offset = mContents.first()->mArea.y + mPadding;
|
||||||
const halnf offset = mContents.first()->mArea.y + padding;
|
|
||||||
|
|
||||||
halnf start = 0;
|
halnf start = 0;
|
||||||
for (auto widget : mContents) {
|
for (auto widget : mContents) {
|
||||||
widget->mArea.y = start;
|
widget->mArea.y = start;
|
||||||
start += widget->mArea.w + padding;
|
start += widget->mArea.w + mPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto widget : mContents) {
|
for (auto widget : mContents) {
|
||||||
|
|
@ -201,17 +210,15 @@ namespace tp {
|
||||||
void updateContentSize() {
|
void updateContentSize() {
|
||||||
mContentSize = 0;
|
mContentSize = 0;
|
||||||
if (mContents.size()) {
|
if (mContents.size()) {
|
||||||
const auto padding = this->getValue("Padding");
|
|
||||||
mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y;
|
mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y;
|
||||||
mContentSize += mContents.last()->mArea.w;
|
mContentSize += mContents.last()->mArea.w;
|
||||||
mContentSize += 2 * padding;
|
mContentSize += 2 * mPadding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOffset(const halnf offset) {
|
void setOffset(const halnf offset) {
|
||||||
if (!mContents.size()) return;
|
if (!mContents.size()) return;
|
||||||
const auto padding = this->getValue("Padding");
|
auto newOffset = offset - mContents.first()->mArea.y + mPadding;
|
||||||
auto newOffset = offset - mContents.first()->mArea.y + padding;
|
|
||||||
for (auto widget : mContents) {
|
for (auto widget : mContents) {
|
||||||
widget->mArea.y += newOffset;
|
widget->mArea.y += newOffset;
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +226,11 @@ namespace tp {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
halnf mContentSize = 0;
|
halnf mContentSize = 0;
|
||||||
|
|
||||||
Buffer<Widget<Events, Canvas>*> mContents;
|
Buffer<Widget<Events, Canvas>*> mContents;
|
||||||
ScrollBarWidget<Events, Canvas> mScroller;
|
ScrollBarWidget<Events, Canvas> mScroller;
|
||||||
|
|
||||||
|
RGBA mDefaultColor;
|
||||||
|
halnf mPadding = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -7,23 +7,9 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class SliderWidget : public Widget<Events, Canvas> {
|
class SliderWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
SliderWidget() {
|
SliderWidget() = default;
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
|
void procBody(const Events& events) override {
|
||||||
if (events.isPressed(InputID::MOUSE1) && this->mArea.isInside(events.getPointer())) {
|
if (events.isPressed(InputID::MOUSE1) && this->mArea.isInside(events.getPointer())) {
|
||||||
mIsSliding = true;
|
mIsSliding = true;
|
||||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||||
|
|
@ -31,44 +17,50 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsSliding) {
|
if (mIsSliding) {
|
||||||
const auto handleSize = this->getValue("HandleSize");
|
|
||||||
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
|
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
canvas.rect(this->mArea, defaultColor, rounding);
|
||||||
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
|
canvas.rect(getHandle(), handleColor, rounding);
|
||||||
canvas.rect(getHandle(), this->getColor("Handle"), this->getValue("Rounding"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RectF getHandle() const {
|
RectF getHandle() const {
|
||||||
const auto handle = this->getValue("HandleSize");
|
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
|
||||||
const auto halfHandle = handle / 2.f;
|
return { left, this->mArea.y, handleSize, this->mArea.w };
|
||||||
const auto left = this->mArea.x + (this->mArea.z - handle) * mFactor;
|
}
|
||||||
return { left, this->mArea.y, handle, this->mArea.w };
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("Slider");
|
||||||
|
defaultColor = wm.getColor("Default", "Base");
|
||||||
|
handleColor = wm.getColor("Handle", "Accent");
|
||||||
|
handleSize = wm.getNumber("HandleSize", 20.f);
|
||||||
|
rounding = wm.getNumber("Rounding", "Rounding");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
halnf mFactor = 0.f;
|
halnf mFactor = 0.f;
|
||||||
bool mIsSliding = false;
|
bool mIsSliding = false;
|
||||||
|
|
||||||
|
RGBA defaultColor;
|
||||||
|
RGBA handleColor;
|
||||||
|
halnf handleSize = 0;
|
||||||
|
halnf rounding = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class NamedSliderWidget : public Widget<Events, Canvas> {
|
class NamedSliderWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
NamedSliderWidget(const char* name = "Value") {
|
explicit NamedSliderWidget(const char* name = "Value") {
|
||||||
mLabel.mLabel = name;
|
mLabel.mLabel = name;
|
||||||
this->mArea = { 0, 0, 100, 30 };
|
this->mArea = { 0, 0, 100, 30 };
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
void procBody(const Events& events) override {
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
const auto widthFirst = this->mArea.z * mFactor;
|
const auto widthFirst = this->mArea.z * mFactor;
|
||||||
const auto widthSecond = this->mArea.z * (1.f - mFactor);
|
const auto widthSecond = this->mArea.z * (1.f - mFactor);
|
||||||
|
|
||||||
|
|
@ -83,12 +75,17 @@ namespace tp {
|
||||||
mSlider.proc(events, this->mArea, rec);
|
mSlider.proc(events, this->mArea, rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
|
||||||
mSlider.draw(canvas);
|
mSlider.draw(canvas);
|
||||||
mLabel.draw(canvas);
|
mLabel.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void updateConfigCache(WidgetManager& wm) {
|
||||||
|
wm.setActiveId("NamedSlider");
|
||||||
|
mSlider.updateConfigCache(wm);
|
||||||
|
mLabel.updateConfigCache(wm);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SliderWidget<Events, Canvas> mSlider;
|
SliderWidget<Events, Canvas> mSlider;
|
||||||
LabelWidget<Events, Canvas> mLabel;
|
LabelWidget<Events, Canvas> mLabel;
|
||||||
|
|
|
||||||
|
|
@ -6,24 +6,9 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class SplitView : public Widget<Events, Canvas> {
|
class SplitView : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
SplitView() {
|
SplitView() = default;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
|
|
||||||
if (!this->mVisible) {
|
|
||||||
mResizeInProcess = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void procBody(const Events& events) override {
|
||||||
mIsHover = getHandle().isInside(events.getPointer());
|
mIsHover = getHandle().isInside(events.getPointer());
|
||||||
|
|
||||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||||
|
|
@ -38,45 +23,55 @@ namespace tp {
|
||||||
mFactor += diff / this->mArea.z;
|
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;
|
mFactor = 0.5f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes whole area
|
// takes whole area
|
||||||
void draw(Canvas& canvas) override {
|
void drawBody(Canvas& canvas) override {
|
||||||
if (!this->mVisible) return;
|
if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor);
|
||||||
|
else if (mIsHover) canvas.rect(getHandle(), mHoveredColor);
|
||||||
if (mResizeInProcess) canvas.rect(getHandle(), this->getColor("Resizing"));
|
else canvas.rect(getHandle(), mHandleColor);
|
||||||
else if (mIsHover) canvas.rect(getHandle(), this->getColor("Hovered"));
|
|
||||||
else canvas.rect(getHandle(), this->getColor("Handle"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RectF getFirst() const {
|
RectF getFirst() const {
|
||||||
return {
|
return { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.w };
|
||||||
this->mArea.x, this->mArea.y, mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f, this->mArea.w
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RectF getSecond() const {
|
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,
|
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 };
|
this->mArea.w };
|
||||||
}
|
}
|
||||||
|
|
||||||
RectF getHandle() const {
|
RectF getHandle() 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, mHandleSize, this->mArea.w };
|
||||||
this->mArea.y,
|
}
|
||||||
this->getValue("HandleSize"),
|
|
||||||
this->mArea.w };
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("SplitView");
|
||||||
|
|
||||||
|
mHandleColor = wm.getColor("Handle", "Accent");
|
||||||
|
mHoveredColor = wm.getColor("Hovered", "Interaction");
|
||||||
|
mResizingColor = wm.getColor("Resizing", "Action");
|
||||||
|
mMinSize = wm.getNumber("Min", 200.f);
|
||||||
|
mHandleSize = wm.getNumber("HandleSize", 7.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
halnf mFactor = 0.7f;
|
halnf mFactor = 0.7f;
|
||||||
bool mResizeInProcess = false;
|
bool mResizeInProcess = false;
|
||||||
bool mIsHover = false;
|
bool mIsHover = false;
|
||||||
|
|
||||||
|
RGBA mHandleColor;
|
||||||
|
RGBA mHoveredColor;
|
||||||
|
RGBA mResizingColor;
|
||||||
|
halnf mMinSize = 0;
|
||||||
|
halnf mHandleSize = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -9,28 +9,13 @@ namespace tp {
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class TextInputWidget : public Widget<Events, Canvas> {
|
class TextInputWidget : public Widget<Events, Canvas> {
|
||||||
public:
|
public:
|
||||||
TextInputWidget() {
|
TextInputWidget() = default;
|
||||||
this->createConfig("TextInput");
|
|
||||||
this->addColor("Accent", "Accent");
|
|
||||||
this->addColor("Base", "Base");
|
|
||||||
this->addValue("Rounding", "Rounding");
|
|
||||||
this->addColor("Hovered", "Interaction");
|
|
||||||
this->addValue("Padding", "Padding");
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
|
||||||
this->mArea = aArea;
|
|
||||||
this->mVisible = areaParent.isOverlap(aArea);
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Canvas& canvas) override {
|
|
||||||
if (!this->mVisible) return;
|
|
||||||
|
|
||||||
|
void drawBody(Canvas& canvas) override {
|
||||||
nChanged = false;
|
nChanged = false;
|
||||||
|
|
||||||
const auto col = this->getColor("Accent");
|
const auto col = mAccentColor;
|
||||||
const auto colSel = this->getColor("Hovered");
|
const auto colSel = mHoveredColor;
|
||||||
|
|
||||||
ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a };
|
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 };
|
ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a };
|
||||||
|
|
@ -38,8 +23,8 @@ namespace tp {
|
||||||
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
|
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
|
||||||
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
|
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, this->getValue("Rounding") * 1.5f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { this->getValue("Padding"), this->getValue("Padding") });
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
|
||||||
|
|
||||||
// ImGui::PushID((int) alni(this));
|
// ImGui::PushID((int) alni(this));
|
||||||
ImGui::Begin(
|
ImGui::Begin(
|
||||||
|
|
@ -65,11 +50,29 @@ namespace tp {
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void updateConfigCache(WidgetManager& wm) override {
|
||||||
|
wm.setActiveId("TextInput");
|
||||||
|
|
||||||
|
mAccentColor = wm.getColor("Accent", "Accent");
|
||||||
|
mBaseColor = wm.getColor("Base", "Base");
|
||||||
|
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||||
|
mHoveredColor = wm.getColor("Hovered", "Accent");
|
||||||
|
mPadding = wm.getNumber("Padding", "Padding");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
enum { mMaxBufferSize = 512 };
|
enum { mMaxBufferSize = 512 };
|
||||||
char mBuff[mMaxBufferSize] = "";
|
char mBuff[mMaxBufferSize] = "";
|
||||||
bool nChanged = false;
|
bool nChanged = false;
|
||||||
std::string mValue;
|
std::string mValue;
|
||||||
std::string mId = "id";
|
std::string mId = "id";
|
||||||
bool mMultiline = false;
|
bool mMultiline = false;
|
||||||
|
|
||||||
|
RGBA mAccentColor;
|
||||||
|
RGBA mHoveredColor;
|
||||||
|
RGBA mBaseColor;
|
||||||
|
halnf mRounding = 0;
|
||||||
|
halnf mPadding = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1,46 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "WidgetConfig.hpp"
|
#include "EventHandler.hpp"
|
||||||
|
#include "WidgetManager.hpp"
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
template <typename Events, typename Canvas>
|
template <typename Events, typename Canvas>
|
||||||
class Widget {
|
class Widget {
|
||||||
public:
|
public:
|
||||||
Widget() {
|
Widget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
||||||
mVisible = areaParent.isOverlap(aArea);
|
mVisible = areaParent.isOverlap(aArea);
|
||||||
|
|
@ -49,18 +17,27 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mArea = aArea;
|
this->mArea = aArea;
|
||||||
|
this->mAreaParent = areaParent;
|
||||||
|
|
||||||
|
procBody(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void draw(Canvas& canvas) {
|
virtual void draw(Canvas& canvas) {
|
||||||
if (!mVisible) {
|
if (!mVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawBody(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void procBody(const Events& events) {}
|
||||||
|
virtual void drawBody(Canvas& canvas) {}
|
||||||
|
|
||||||
|
virtual void updateConfigCache(WidgetManager& wm) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GlobalGUIConfig* globalCfg = gGlobalGUIConfig;
|
|
||||||
WidgetConfig* cfg = nullptr;
|
|
||||||
RectF mArea;
|
RectF mArea;
|
||||||
|
RectF mAreaParent;
|
||||||
bool mVisible = false;
|
bool mVisible = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
144
Widgets/public/WidgetManager.hpp
Normal file
144
Widgets/public/WidgetManager.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Animations.hpp"
|
||||||
|
#include "Map.hpp"
|
||||||
|
#include "Rect.hpp"
|
||||||
|
|
||||||
|
#include "InputCodes.hpp"
|
||||||
|
#include "Buffer.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
|
||||||
|
struct WidgetConfig {
|
||||||
|
|
||||||
|
struct Shortcut {
|
||||||
|
struct Condition {
|
||||||
|
std::string name;
|
||||||
|
std::string state;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string callbackName;
|
||||||
|
|
||||||
|
Shortcut() = default;
|
||||||
|
Shortcut(const InitialierList<Condition>&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Parameter {
|
||||||
|
enum Type { NONE, VAL, COL };
|
||||||
|
|
||||||
|
halnf value = 0.f;
|
||||||
|
RGBA color = {};
|
||||||
|
Type type = NONE;
|
||||||
|
bool globalReference = false;
|
||||||
|
std::string globalId;
|
||||||
|
|
||||||
|
Parameter() = default;
|
||||||
|
|
||||||
|
explicit Parameter(halnf val) {
|
||||||
|
type = VAL;
|
||||||
|
value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit Parameter(const RGBA& val) {
|
||||||
|
type = COL;
|
||||||
|
color = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit Parameter(const std::string& id, const Type& referenceType) {
|
||||||
|
type = referenceType;
|
||||||
|
globalId = id;
|
||||||
|
globalReference = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<std::string, Parameter> mParameters;
|
||||||
|
Buffer<Shortcut> mShortcuts;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WidgetManager {
|
||||||
|
public:
|
||||||
|
using Parameter = WidgetConfig::Parameter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WidgetManager() { initGlobalParameters(); }
|
||||||
|
~WidgetManager() { mConfigurations.removeAll(); }
|
||||||
|
|
||||||
|
const RGBA& getColor(const std::string& parameterId, const RGBA& defaultValue) {
|
||||||
|
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||||
|
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||||
|
return parameter.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RGBA& getColor(const std::string& parameterId, const char* globalRef) {
|
||||||
|
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||||
|
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::COL));
|
||||||
|
return parameter.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
halnf getNumber(const std::string& parameterId, halnf defaultValue) {
|
||||||
|
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||||
|
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||||
|
return parameter.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
halnf getNumber(const std::string& parameterId, const char* globalRef) {
|
||||||
|
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||||
|
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::VAL));
|
||||||
|
return parameter.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setActiveId(const std::string& id) { mActiveId = id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
WidgetConfig& getWidgetConfig(const std::string& id) {
|
||||||
|
auto idx = mConfigurations.presents(id);
|
||||||
|
if (idx) return mConfigurations.getSlotVal(idx);
|
||||||
|
mConfigurations.put(id, {});
|
||||||
|
return mConfigurations.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Parameter& getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue) {
|
||||||
|
auto idx = config.mParameters.presents(id);
|
||||||
|
|
||||||
|
if (!idx) {
|
||||||
|
config.mParameters.put(id, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
Parameter& parameter = config.mParameters.get(id);
|
||||||
|
|
||||||
|
if (parameter.globalReference) {
|
||||||
|
return mGlobalConfig.mParameters.get(parameter.globalId);
|
||||||
|
} else {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initGlobalParameters() {
|
||||||
|
auto& params = mGlobalConfig.mParameters;
|
||||||
|
|
||||||
|
params.put("FontSize", Parameter(15.f));
|
||||||
|
|
||||||
|
params.put("FontSizeDim", Parameter(12.f));
|
||||||
|
params.put("Rounding", Parameter(5.f));
|
||||||
|
params.put("Padding", Parameter(5.f));
|
||||||
|
params.put("HandleSize", Parameter(5.f));
|
||||||
|
|
||||||
|
params.put("Background", Parameter(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
|
||||||
|
params.put("Base", Parameter(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
|
||||||
|
params.put("Accent", Parameter(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
|
||||||
|
params.put("Interaction", Parameter(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
|
||||||
|
params.put("Action", Parameter(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
|
||||||
|
params.put("Front", Parameter(RGBA{ 1.f, 1.f, 1.f, 1.f }));
|
||||||
|
params.put("FrontDim", Parameter(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Map<std::string, WidgetConfig> mConfigurations;
|
||||||
|
WidgetConfig mGlobalConfig;
|
||||||
|
|
||||||
|
RGBA mErrorColor = { 0, 0, 0, 1 };
|
||||||
|
halnf mErrorNumber = 0;
|
||||||
|
|
||||||
|
std::string mActiveId;
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue