Replace Old Widgets

This commit is contained in:
IlyaShurupov 2024-10-18 10:56:42 +03:00
parent cce8f0e1bc
commit fcd5eb2d2a
81 changed files with 388 additions and 278 deletions

View file

@ -0,0 +1,21 @@
project(Widgets)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
### -------------------------- Applications -------------------------- ###
add_executable(SimpleGui examples/SimpleGUI.cpp)
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(ChatGui examples/ChatGUI.cpp)
target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -1,12 +1,12 @@
#include "EditorWidget.hpp"
#include "GraphicApplication.hpp"
#include "WidgetApplication.hpp"
#include "RootWidget.hpp"
using namespace tp;
class EditorGUI : public Application {
class EditorGUI : public WidgetApplication {
public:
EditorGUI() {
auto canvas = this->mGraphics->getCanvas();
@ -14,25 +14,14 @@ public:
mEditor.loadDefaults();
setRoot(mGui);
// mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 3, 3, 2 }, { 0, 0, 1 });
}
~EditorGUI() override { delete mGui; }
void processFrame(EventHandler* eventHandler, halnf delta) override {
auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui->setArea(rec);
mGui->setVisible(true);
mGui->updateConfigWrapper(mWidgetManager);
mGui->procWrapper(*eventHandler, rec);
}
void drawFrame(Canvas* canvas) override { mGui->drawWrapper(*canvas); }
private:
Editor mEditor;
WidgetManager mWidgetManager;
EditorWidget* mGui;
};

View file

@ -57,6 +57,8 @@ void Editor::loadDefaults() {
}
void Editor::setViewportSize(const Vec2F& size) {
if (size.x < 0 || size.y < 0) return;
// TODO remove
// mScene.mCamera.rotate(0.01f, 0.0);

View file

@ -1,6 +1,8 @@
#include "Widgets.hpp"
#include "Widget.hpp"
#include "DockWidget.hpp"
#include "Editor.hpp"
#include "FloatingWidget.hpp"
namespace tp {
@ -12,15 +14,17 @@ namespace tp {
mCanvas = canvas;
}
~ViewportWidget() { mCanvas->deleteImageHandle(mImage); }
~ViewportWidget() override { mCanvas->deleteImageHandle(mImage); }
void eventProcess(const Events& events) override { mEditor->setViewportSize(this->mArea.size); }
void process(const EventHandler& events) override {
mEditor->setViewportSize(getArea().size);
}
void eventDraw(Canvas& canvas) override {
void draw(Canvas& canvas) override {
mEditor->renderViewport();
canvas.updateTextureID(mImage, mEditor->getViewportTexID());
canvas.drawImage(this->mArea, &mImage, PI);
canvas.drawImage(getArea().relative(), &mImage, PI);
}
public:
@ -30,98 +34,96 @@ namespace tp {
Canvas::ImageHandle mImage;
};
class EditorWidget : public WorkspaceWidget {
class EditorWidget : public DockWidget {
public:
EditorWidget(Canvas* canvas, Editor* editor) :
mViewport(canvas, editor) {
mEditor = editor;
mDockSpace.addSideWidget(&mNavigationMenu, DockWidget::RIGHT);
mDockSpace.addSideWidget(&mRenderMenu, DockWidget::LEFT);
mDockSpace.setCenterWidget(&mViewport);
mPanel.setText("Controls");
mPanel.addToMenu(&mNavigationMenu);
mPanel.addToMenu(&mRenderMenu);
dockWidget(&mPanel, DockLayout::RIGHT);
setCenterWidget(&mViewport);
// Render
{
mRenderPathTracer.setLabel("Render with Path Tracer");
mRenderRaster.setLabel("Render with Raster");
mRenderDeNoise.setLabel("Denoise (IntelOpenImage)");
mRenderPathTracer.setText("Render with Path Tracer");
mRenderRaster.setText("Render with Raster");
mRenderDeNoise.setText("Denoise (IntelOpenImage)");
mRenderMenu.addWidgetToMenu(&mRenderPathTracer);
mRenderMenu.addWidgetToMenu(&mRenderRaster);
mRenderMenu.addWidgetToMenu(&mRenderDeNoise);
mRenderMenu.addToMenu(&mRenderPathTracer);
mRenderMenu.addToMenu(&mRenderRaster);
mRenderMenu.addToMenu(&mRenderDeNoise);
mRenderMenu.setLabel("Render");
mRenderMenu.setText("Render");
}
// Navigation
{
mNavigationPan.setLabel("Pan");
mNavigationOrbit.setLabel("Orbit");
mNavigationZoom.setLabel("Zoom");
mNavigationReset.setLabel("Reset");
mNavigationPan.setText("Pan");
mNavigationOrbit.setText("Orbit");
mNavigationZoom.setText("Zoom");
mNavigationReset.setText("Reset");
mNavigationMenu.addWidgetToMenu(&mNavigationPan);
mNavigationMenu.addWidgetToMenu(&mNavigationOrbit);
mNavigationMenu.addWidgetToMenu(&mNavigationZoom);
mNavigationMenu.addWidgetToMenu(&mNavigationReset);
mNavigationMenu.addToMenu(&mNavigationPan);
mNavigationMenu.addToMenu(&mNavigationOrbit);
mNavigationMenu.addToMenu(&mNavigationZoom);
mNavigationMenu.addToMenu(&mNavigationReset);
mNavigationMenu.setLabel("Navigation");
mNavigationMenu.setText("Navigation");
}
mRenderPathTracer.mCallback = [this]() {
mRenderPathTracer.setAction([this]() {
mEditor->renderPathFrame();
mEditor->setRenderType(Editor::RenderType::PATH_TRACER);
};
});
mRenderRaster.mCallback = [this]() { mEditor->setRenderType(Editor::RenderType::RASTER); };
mRenderDeNoise.mCallback = [this]() { mEditor->denoisePathRenderBuffers(); };
mNavigationOrbit.mCallback = [this]() { mNavigationType = ORBIT; };
mNavigationPan.mCallback = [this]() { mNavigationType = PAN; };
mNavigationZoom.mCallback = [this](){ mNavigationType = ZOOM; };
mNavigationReset.mCallback = [this]() { mEditor->navigationReset(); };
mRenderRaster.setAction( [this]() { mEditor->setRenderType(Editor::RenderType::RASTER); });
mRenderDeNoise.setAction( [this]() { mEditor->denoisePathRenderBuffers(); });
mNavigationOrbit.setAction( [this]() { mNavigationType = ORBIT; });
mNavigationPan.setAction( [this]() { mNavigationType = PAN; });
mNavigationZoom.setAction( [this](){ mNavigationType = ZOOM; });
mNavigationReset.setAction( [this]() { mEditor->navigationReset(); });
}
void eventProcess(const Events& events) override {
// navigation
{
const auto& activeArea = mViewport.mArea;
if (mViewport.isHolding()) {
switch (mNavigationType) {
case ORBIT: mEditor->navigationOrbit(events.getPointerDelta() / activeArea.size * 3); break;
void process(const EventHandler& events) override {
DockWidget::process(events);
case PAN:
{
auto pointer = (((events.getPointer() - activeArea.pos) / activeArea.size) - 0.5f) * 2;
auto prevPointer = (((events.getPointerPrev() - activeArea.pos) / activeArea.size) - 0.5f) * 2;
mEditor->navigationPan(prevPointer, pointer);
}
break;
auto pointer = events.getPointer();
auto pointerPrev = events.getPointerPrev();
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
}
const auto& activeArea = mViewport.getArea();
if (activeArea.isInside(pointer) && events.isDown(InputID::MOUSE1)) {
switch (mNavigationType) {
case ORBIT: mEditor->navigationOrbit(events.getPointerDelta() / activeArea.size * 3); break;
case PAN:
{
auto pointerRelative = (((pointer - activeArea.pos) / activeArea.size) - 0.5f) * 2;
auto prevPointerRelative = (((pointerPrev - activeArea.pos) / activeArea.size) - 0.5f) * 2;
mEditor->navigationPan(prevPointerRelative, pointerRelative);
}
break;
case ZOOM: mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y)); break;
}
}
WorkspaceWidget::eventProcess(events);
}
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBaseColor); }
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("3DEditor");
mBaseColor = wm.getColor("Base", "Base");
}
void draw(Canvas& canvas) override { canvas.rect(getArea().relative(), mBaseColor); }
public:
Editor* mEditor = nullptr;
// SplitView mSplitView;
ViewportWidget mViewport;
// ScrollableWindow mSettingsWidget;
FloatingMenu mPanel;
// Controls
FloatingWidget mRenderMenu;
FloatingMenu mRenderMenu;
ButtonWidget mRenderPathTracer;
ButtonWidget mRenderRaster;
ButtonWidget mRenderDeNoise;
@ -129,7 +131,7 @@ namespace tp {
// Navigation
enum NavigationType { ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
FloatingWidget mNavigationMenu;
FloatingMenu mNavigationMenu;
ButtonWidget mNavigationPan;
ButtonWidget mNavigationOrbit;
ButtonWidget mNavigationZoom;

View file

@ -20,7 +20,6 @@ add_subdirectory(Graphics)
add_subdirectory(DataAnalysis)
add_subdirectory(Objects)
add_subdirectory(Widgets)
add_subdirectory(WidgetsNew)
add_subdirectory(LibraryViewer)
add_subdirectory(RasterRender)
add_subdirectory(3DScene)

View file

@ -117,6 +117,10 @@ void Canvas::popClamp() {
}
}
const RectF& Canvas::getClampedArea() const {
return mScissors.last();
}
void Canvas::text(
const char* string, const RectF& aRec, halnf size, Align align, halnf marging, const RGBA& col
) {

View file

@ -59,6 +59,7 @@ namespace tp {
void pushClamp(const RectF& rec);
void popClamp();
const RectF& getClampedArea() const;
void debugCross(RectF rec, const RGBA& col);
void rect(RectF rec, const RGBA& col, halnf round = 0);

View file

@ -1,10 +1,10 @@
#include "GUI.hpp"
#include "GraphicApplication.hpp"
#include "WidgetApplication.hpp"
using namespace tp;
class LibraryViewer : public Application {
class LibraryViewer : public WidgetApplication {
public:
LibraryViewer() :
gui(&library, &player) {
@ -12,24 +12,14 @@ public:
library.checkExisting();
gui.updateTracks();
setRoot(&gui);
}
void processFrame(EventHandler* eventHandler, halnf delta) override {
auto rec = RectF{ { 0, 0 }, mWindow->getSize() };
gui.setVisible(true);
gui.setArea(rec);
gui.updateConfigWrapper(mWidgetManager);
gui.procWrapper(*eventHandler, rec);
}
void drawFrame(Canvas* canvas) override { gui.drawWrapper(*canvas); }
private:
Player player;
Library library;
tp::WidgetManager mWidgetManager;
LibraryWidget gui;
};

View file

@ -1,7 +1,6 @@
#include "Library.hpp"
#include "LocalConnection.hpp"
#include "WidgetBase.hpp"
#include "picojson.h"
#include <filesystem>

View file

@ -2,7 +2,8 @@
#include "Library.hpp"
#include "Player.hpp"
#include "Widgets.hpp"
#include "FloatingWidget.hpp"
#include "DockWidget.hpp"
#include "imgui.h"
@ -10,54 +11,83 @@ namespace tp {
class TrackWidget : public Widget {
public:
explicit TrackWidget(const Track* track = nullptr) :
mTrack(track) {
this->mArea.w = 70;
col.mColor.setAnimTime(0);
col.mColor.setNoTransition({ 0.15f, 0.15f, 0.15f, 0.f });
enum State {
IDLE,
HOVER,
SELECTED,
};
void eventProcess(const Events& events) override {
mSelected = false;
if (!mTrack) return;
if (this->mArea.isInside(events.getPointer())) {
col.set({ 0.15f, 0.15f, 0.15f, 1.f });
mSelected = events.isReleased(InputID::MOUSE1);
} else {
col.set({ 0.15f, 0.15f, 0.15f, 0.f });
explicit TrackWidget(const Track* track = nullptr) :
mTrack(track) {
getLayout()->setMinSize({ 70, 70 });
};
void process(const EventHandler& events) override {
mState = IDLE;
if (!mTrack) {
mState = IDLE;
return;
}
switch (mState) {
case HOVER:
case IDLE:
mState = getArea().relative().isInside(events.getPointer()) ? HOVER : IDLE;
if (events.isPressed(InputID::MOUSE1)) {
mState = SELECTED;
}
break;
case SELECTED:
break;
}
}
void eventDraw(Canvas& canvas) override {
void draw(Canvas& canvas) override {
if (!mTrack) return;
auto area = getArea().relative();
canvas.rect(this->mArea, col.get(), 4.f);
switch (mState) {
case IDLE: canvas.rect(area, colorIdle, rounding); break;
case HOVER: canvas.rect(area, colorHover, rounding); break;
case SELECTED: canvas.rect(area, colorSelected, rounding); break;
}
const RectF imageArea = {
this->mArea.x + margin, this->mArea.y + margin, this->mArea.w - margin * 2, this->mArea.w - margin * 2
const RectF imageArea = { area.x + margin, area.y + margin, area.w - margin * 2, area.w - margin * 2 };
canvas.rect(imageArea, colorImage, rounding);
const RectF textArea = {
area.x + area.w + margin, area.y + margin, area.z - area.w - margin * 2, area.w - margin * 2
};
canvas.rect(imageArea, { 0.25f, 0.25f, 0.25f, 1.f }, 4.f);
const RectF textArea = { this->mArea.x + this->mArea.w + margin,
this->mArea.y + margin,
this->mArea.z - this->mArea.w - margin * 2,
this->mArea.w - margin * 2 };
// canvas.rect(textArea, { 0.25f, 0.25f, 0.25f, 1.f }, 4.f);
const RectF textAreaName = { textArea.x, textArea.y, textArea.z, textArea.w * 0.5f };
const RectF textAreaAuthor = { textArea.x, textArea.y + textArea.w * 0.5f, textArea.z, textArea.w * 0.5f };
canvas.text(mTrack->mName.c_str(), textAreaName, 15.f, Canvas::LC, 4.f, { 0.9f, 0.9f, 0.9f, 1.f });
canvas.text(mTrack->mArtist.c_str(), textAreaAuthor, 12.f, Canvas::LC, 4.f, { 0.8f, 0.8f, 0.8f, 1.f });
canvas.text(mTrack->mName.c_str(), textAreaName, 15.f, Canvas::LC, rounding, colorNameTrack);
canvas.text(mTrack->mArtist.c_str(), textAreaAuthor, 12.f, Canvas::LC, rounding, colorNameArtist);
}
[[nodiscard]] bool processesEvents() const override { return true; }
public:
halnf margin = 5.f;
AnimColor col;
const Track* mTrack;
bool mSelected = false;
State mState = IDLE;
private:
halnf margin = 5.f;
halnf rounding = 5.f;
RGBA colorIdle = 0;
RGBA colorNameTrack = { 0.9f, 0.9f, 0.9f, 1.f };
RGBA colorNameArtist = { 0.8f, 0.8f, 0.8f, 1.f };
RGBA colorImage = { 0.5, 0.5, 0.5, 1.0 };
RGBA colorHover = { 0.13, 0.13, 0.13, 0.9 };
RGBA colorSelected = { 0.43, 0.43, 0.43, 0.9 };
};
class TrackInfoWidget : public Widget {
@ -74,21 +104,23 @@ namespace tp {
items.append({ "Date Last Played" });
}
void eventDraw(Canvas&) override {
void draw(Canvas&) override {
if (!mTrack) return;
// canvas.rect(this->mArea, { 0.13f, 0.13f, 0.13f, 1.f }, 4.f);
renderUI();
}
void renderUI() {
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
// auto area = getArea();
// ImGui::SetNextWindowPos({ area.x, this->mArea.y });
// ImGui::SetNextWindowSize({ area.z, this->mArea.w });
ImGui::Begin(
"InfoWindow",
nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoResize
nullptr //,
//ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground |
// ImGuiWindowFlags_NoResize
);
if (mTrack) {
@ -184,18 +216,18 @@ namespace tp {
int filterExisting = 0; // all existing no-existing
};
class LibraryWidget : public WorkspaceWidget {
class LibraryWidget : public DockWidget {
public:
LibraryWidget(Library* lib, Player* player) {
mLibrary = (lib);
mPlayer = (player);
updateTracks();
// updateTracks();
mCurrentTrackInfo.mPlayer = mPlayer;
mDockSpace.setCenterWidget(&mSongList);
mDockSpace.addSideWidget(&mCurrentTrackInfo, DockWidget::RIGHT);
setCenterWidget(&mSongList);
dockWidget(&mCurrentTrackInfo, DockLayout::RIGHT);
// this->mChildWidgets.pushBack(&mCurrentTrackInfo);
// this->mChildWidgets.pushBack(&mCurrentTrack);
@ -203,24 +235,30 @@ namespace tp {
void updateTracks() {
mTracks.clear();
for (auto track : mTracks) {
delete track.data();
}
for (auto track : mLibrary->mTraks) {
mTracks.append(TrackWidget(&track.data()));
mTracks.append(new TrackWidget(&track.data()));
}
}
void eventProcess(const Events& events) override {
void process(const EventHandler& events) override {
filter();
for (auto track : mSongList.getContent()) {
auto trackWidget = (TrackWidget*) track.data();
if (trackWidget->mSelected) {
mCurrentTrackInfo.mTrack = trackWidget->mTrack;
if (auto trackWidget = dynamic_cast<TrackWidget*>(track.data())) {
if (trackWidget->mState == TrackWidget::SELECTED) {
mCurrentTrackInfo.mTrack = trackWidget->mTrack;
}
}
}
// mCurrentTrack.proc(events, this->mArea, mSplitView.getFirst());
WorkspaceWidget::eventProcess(events);
DockWidget::process(events);
}
// void eventDraw(Canvas& canvas) override {
@ -230,7 +268,7 @@ namespace tp {
void filter() {
if (!mCurrentTrackInfo.isSongFilterChanged) return;
mSongList.clearContent();
mSongList.clearChildren();
for (auto track : mTracks) {
if (!mCurrentTrackInfo.songFilter.PassFilter(track->mTrack->mName.c_str()) &&
@ -252,7 +290,7 @@ namespace tp {
break;
}
mSongList.addWidget(&track.data());
mSongList.addToMenu(track.data());
}
mCurrentTrackInfo.isSongFilterChanged = false;
@ -262,9 +300,9 @@ namespace tp {
Library* mLibrary = nullptr;
Player* mPlayer = nullptr;
Buffer<TrackWidget> mTracks;
Buffer<TrackWidget*> mTracks;
ScrollableWindow mSongList;
FloatingMenu mSongList;
TrackInfoWidget mCurrentTrackInfo;
TrackWidget mCurrentTrack;
};

View file

@ -1,29 +1,19 @@
#include "GraphicApplication.hpp"
#include "WidgetApplication.hpp"
#include "Sketch3D.hpp"
#include "Sketch3DWidget.hpp"
using namespace tp;
class Sketch3DApplication : public Application {
class Sketch3DApplication : public WidgetApplication {
public:
Sketch3DApplication() :
mGui(*mGraphics->getCanvas(), { 1920, 1080 }) {}
void processFrame(EventHandler* eventHandler, halnf delta) override {
auto rec = RectF({ 0, 0 }, mWindow->getSize());
mGui.setVisible(true);
mGui.setArea(rec);
mGui.updateConfigWrapper(mWidgetManager);
mGui.procWrapper(*eventHandler, rec);
mGui(*mGraphics->getCanvas(), { 1920, 1080 }) {
setRoot(&mGui);
}
void drawFrame(Canvas* canvas) override { mGui.drawWrapper(*canvas); }
private:
WidgetManager mWidgetManager;
Sketch3DGUI mGui;
};

View file

@ -1,7 +1,9 @@
#pragma once
#include "Sketch3D.hpp"
#include "Widgets.hpp"
#include "Widget.hpp"
#include "DockWidget.hpp"
#include "FloatingWidget.hpp"
namespace tp {
@ -17,30 +19,31 @@ namespace tp {
~Sketch3DWidget() { mCanvas->deleteImageHandle(mImage); }
void eventProcess(const Events& events) override {
if (!this->mArea.isInside(events.getPointer())) {
void process(const EventHandler& events) override {
auto area = getArea().relative();
Vec2F pointer = events.getPointer();
auto crs = events.getPointer();
if (!area.isInside(events.getPointer())) {
return;
}
auto crs = (events.getPointer() - this->mArea.pos);
crs.x /= this->mArea.z;
crs.y /= this->mArea.w;
crs.x /= area.z;
crs.y /= area.w;
crs = (crs - 0.5) * 2;
// TODO : make better api for events
Vec2F absolutePos = events.getPointer() - this->mArea.pos;
if (events.isPressed(InputID::MOUSE1)) {
mAction = true;
} else if (events.isReleased(InputID::MOUSE1)) {
mAction = false;
}
Vec2F relativePos = ((absolutePos / this->mArea.size) - 0.5f) * 2.f;
Vec2F relativePosPrev = ((mActionPosAbsolutePrev / this->mArea.size) - 0.5f) * 2.f;
Vec2F relativePos = ((pointer / area.size) - 0.5f) * 2.f;
Vec2F relativePosPrev = ((mActionPosAbsolutePrev / area.size) - 0.5f) * 2.f;
Vec2F relativeDelta = relativePos - relativePosPrev;
mProject.mCamera.setRatio(this->mArea.w / this->mArea.z);
mProject.mCamera.setRatio(area.w / area.z);
switch (mMode) {
case Mode::MOVE:
@ -50,7 +53,7 @@ namespace tp {
}
case Mode::ZOOM:
{
halnf factor = absolutePos.y / mActionPosAbsolutePrev.y;
halnf factor = pointer.y / mActionPosAbsolutePrev.y;
if (mAction) mProject.mCamera.zoom(factor);
break;
}
@ -61,22 +64,25 @@ namespace tp {
}
case Mode::DRAW:
{
mProject.sample(events.getPointerPressure(), this->mArea.w / this->mArea.z, crs);
mProject.sample(events.getPointerPressure(), area.w / area.z, crs);
break;
}
default: break;
}
mActionPosAbsolutePrev = absolutePos;
mActionPosAbsolutePrev = pointer;
}
void eventDraw(Canvas& canvas) override {
mRenderer.renderToTexture(&mProject, this->mArea.size);
canvas.drawImage(this->mArea, &mImage, 0, 1, 12);
void draw(Canvas& canvas) override {
auto area = getArea().relative();
mRenderer.renderToTexture(&mProject, area.size);
canvas.drawImage(area, &mImage, 0, 1, 12);
}
void setColor(const RGBA& color) { ((PencilBrush*) mProject.mBrushes.get("pencil"))->mCol = color; }
[[nodiscard]] bool processesEvents() const override { return true; }
public:
enum class Mode { MOVE, ROTATE, ZOOM, DRAW, NONE } mMode = Mode::NONE;
@ -90,62 +96,72 @@ namespace tp {
Canvas* mCanvas = nullptr;
};
class Sketch3DGUI : public WorkspaceWidget {
class Sketch3DGUI : public DockWidget {
public:
Sketch3DGUI(Canvas& canvas, Vec2F renderResolution) :
mViewport(canvas, renderResolution)
{
explicit Sketch3DGUI(Canvas& canvas, Vec2F renderResolution) :
DockWidget(),
mViewport(canvas, renderResolution) {
mControls.addWidgetToMenu(&mDrawButton);
mControls.addWidgetToMenu(&mMoveButton);
mControls.addWidgetToMenu(&mRotateButton);
mControls.addWidgetToMenu(&mZoomButton);
mControls.addToMenu(&mDrawButton);
mControls.addToMenu(&mMoveButton);
mControls.addToMenu(&mRotateButton);
mControls.addToMenu(&mZoomButton);
mColorPicker.addWidgetToMenu(&mRed);
mColorPicker.addWidgetToMenu(&mGreen);
mColorPicker.addWidgetToMenu(&mBlue);
mColorPicker.addToMenu(&mRed);
mColorPicker.addToMenu(&mGreen);
mColorPicker.addToMenu(&mBlue);
mDockSpace.setCenterWidget(&mViewport);
setCenterWidget(&mViewport);
mFloatingLayer.mChildWidgets.pushBack(&mControls);
mFloatingLayer.mChildWidgets.pushBack(&mColorPicker);
mPanel.addToMenu(&mControls);
mPanel.addToMenu(&mColorPicker);
// addChild(&mPanel);
dockWidget(&mPanel, DockLayout::RIGHT);
mDrawButton.setAction([this]() { mViewport.mMode = Sketch3DWidget::Mode::DRAW; });
mMoveButton.setAction([this]() { mViewport.mMode = Sketch3DWidget::Mode::MOVE; });
mRotateButton.setAction([this]() { mViewport.mMode = Sketch3DWidget::Mode::ROTATE; });
mZoomButton.setAction([this]() { mViewport.mMode = Sketch3DWidget::Mode::ZOOM; });
mDrawButton.setText("Draw");
mMoveButton.setText("Pan");
mRotateButton.setText("Orbit");
mZoomButton.setText("Zoom");
mPanel.setText("Controls");
mControls.setText("Tools");
mColorPicker.setText("Color");
mPanel.setArea({110, 110, 300, 500 });
mControls.setArea({0, 0, 300, 400 });
mColorPicker.setArea({0, 0, 300, 300 });
mDrawButton.mCallback = [this]() { mViewport.mMode = Sketch3DWidget::Mode::DRAW; };
mMoveButton.mCallback = [this]() { mViewport.mMode = Sketch3DWidget::Mode::MOVE; };
mRotateButton.mCallback = [this]() { mViewport.mMode = Sketch3DWidget::Mode::ROTATE; };
mZoomButton.mCallback = [this]() { mViewport.mMode = Sketch3DWidget::Mode::ZOOM; };
}
void eventProcess(const Events& events) override {
WorkspaceWidget::eventProcess(events);
void process(const EventHandler& events) override {
DockWidget::process(events);
mViewport.setColor(RGBA(mRed.mSlider.mFactor, mGreen.mSlider.mFactor, mBlue.mSlider.mFactor, 1.f));
mViewport.setColor(RGBA(mRed.val(), mGreen.val(), mBlue.val(), 1.f));
}
void eventDraw(Canvas& canvas) override { canvas.rect(this->mArea, mBackgroundColor, mRounding); }
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("Sketch3DGui");
mBackgroundColor = wm.getColor("Background", "Background");
mRounding = wm.getNumber("Rounding", "Rounding");
}
void draw(Canvas& canvas) override { canvas.rect(getArea().relative(), mBackgroundColor, mRounding); }
private:
Sketch3DWidget mViewport;
ScrollableWindow mOptions;
FloatingWidget mControls;
ButtonWidget mDrawButton = ButtonWidget("Draw", { 0, 0, 100, 30 });
ButtonWidget mMoveButton = ButtonWidget("Pan", { 0, 0, 100, 30 });
ButtonWidget mRotateButton = ButtonWidget("Orbit", { 0, 0, 100, 30 });
ButtonWidget mZoomButton = ButtonWidget("Zoom", { 0, 0, 100, 30 });
FloatingMenu mPanel;
FloatingWidget mColorPicker;
NamedSliderWidget mRed = NamedSliderWidget("Red");
NamedSliderWidget mGreen = NamedSliderWidget("Green");
NamedSliderWidget mBlue = NamedSliderWidget("Blue");
FloatingMenu mControls;
ButtonWidget mDrawButton;
ButtonWidget mMoveButton;
ButtonWidget mRotateButton;
ButtonWidget mZoomButton;
FloatingMenu mColorPicker;
SliderWidget mRed;
SliderWidget mGreen;
SliderWidget mBlue;
RGBA mBackgroundColor;
halnf mRounding = 0;

View file

@ -5,17 +5,13 @@ file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ./public/layouts ./public/mangers ./public/widgets)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
### -------------------------- Applications -------------------------- ###
add_executable(SimpleGui examples/SimpleGUI.cpp)
target_link_libraries(SimpleGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(SimpleGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(ChatGui examples/ChatGUI.cpp)
target_link_libraries(ChatGui ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(ChatGui PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
add_executable(Widgets2Example examples/Example.cpp)
target_link_libraries(Widgets2Example ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(Widgets2Example PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")

View file

@ -1,5 +1,5 @@
#include "GraphicApplication.hpp"
#include "WidgetApplication.hpp"
#include "RootWidget.hpp"
#include "FloatingWidget.hpp"
@ -10,10 +10,10 @@
using namespace tp;
class WidgetApplication : public Application {
class Example : public WidgetApplication {
public:
WidgetApplication() {
exampleBasic();
Example() {
exampleScrolling();
}
void exampleAll() {
@ -33,7 +33,7 @@ public:
menus[0].addToMenu(&menu);
}
mRootWidget.setRootWidget(&dock);
setRoot(&dock);
}
void exampleBasic() {
@ -46,7 +46,7 @@ public:
widget.addChild(&button);
widget.addChild(&slider);
mRootWidget.setRootWidget(&widget);
setRoot(&widget);
}
void exampleScrolling() {
@ -55,7 +55,7 @@ public:
static ButtonWidget buttons[10];
static ScrollableBarWidget scrollBar;
mRootWidget.setRootWidget(&widget);
setRoot(&widget);
widget.addChild(&scrollBar);
widget.addChild(&content);
@ -91,7 +91,7 @@ public:
RootWidget::setWidgetArea(openButton, { 333, 333, 222, 222 });
mRootWidget.setRootWidget(&root);
setRoot(&root);
}
void exampleNestedMenus() {
@ -100,7 +100,7 @@ public:
static FloatingMenu menu2;
static ButtonWidget buttons[15];
mRootWidget.setRootWidget(&dock);
setRoot(&dock);
dock.addChild(&menu1);
dock.addChild(&menu2);
@ -140,7 +140,7 @@ public:
static Widget widgets[15];
static ButtonWidget buttons[15];
mRootWidget.setRootWidget(&widgets[0]);
setRoot(&widgets[0]);
widgets[0].addChild(&widgets[1]);
@ -173,7 +173,7 @@ public:
static FloatingMenu menu2;
static ButtonWidget buttons[15];
mRootWidget.setRootWidget(&dock);
setRoot(&dock);
dock.addChild(&menu2);
dock.addChild(&menu1);
@ -203,29 +203,11 @@ public:
RootWidget::setWidgetArea(menu2, { 300, 100, 150, 500 });
RootWidget::setWidgetArea(menu1, { 100, 100, 150, 300 });
}
void processFrame(EventHandler* eventHandler, halnf deltaTime) override {
const auto rec = RectF({ 0, 0 }, mWindow->getSize());
mRootWidget.processFrame(eventHandler, rec);
}
void drawFrame(Canvas* canvas) override {
mRootWidget.drawFrame(*canvas);
// drawDebug();
}
bool forceNewFrame() override {
return mRootWidget.needsUpdate();
}
private:
RootWidget mRootWidget;
};
int main() {
{
WidgetApplication gui;
Example gui;
gui.run();
}
}

View file

@ -80,10 +80,12 @@ void RootWidget::drawRecursion(Canvas& canvas, Widget* active, const Vec2F& pos)
canvas.setOrigin(pos);
canvas.pushClamp({ pos, active->getArea().size });
active->draw(canvas);
if (canvas.getClampedArea().size.length2() > EPSILON) {
active->draw(canvas);
for (auto child = active->mDepthOrder.lastNode(); child; child = child->prev) {
drawRecursion(canvas, child->data, pos + child->data->getArea().pos);
for (auto child = active->mDepthOrder.lastNode(); child; child = child->prev) {
drawRecursion(canvas, child->data, pos + child->data->getArea().pos);
}
}
canvas.setOrigin(pos);
@ -150,3 +152,4 @@ void RootWidget::closePopup(Widget* widget) {
void RootWidget::lockFocus(Widget* widget) { mUpdateManager.lockFocus(widget); }
void RootWidget::freeFocus(Widget* widget) { mUpdateManager.freeFocus(widget); }
bool RootWidget::isDebug() const { return gDebugWidget.isDebug(); }

View file

@ -51,6 +51,11 @@ void Widget::removeChild(Widget* child) {
child->triggerWidgetUpdate("parent changed");
}
void Widget::clear() {
mChildren.clear();
mDepthOrder.removeAll();
}
void Widget::endAnimations() { mArea.endAnimation(); }
bool Widget::processesEvents() const { return false; }
void Widget::updateAnimations() { mArea.updateCurrentRect(); }

View file

@ -0,0 +1,10 @@
#include "WidgetApplication.hpp"
#include "imgui.h"
using namespace tp;
void WidgetApplication::debugUI() {
ImGui::Text("Proc ms : %i", (int) mProcTime);
ImGui::SameLine(); ImGui::Text("Draw ms : %i", (int) mDrawTime);
}

View file

@ -169,7 +169,7 @@ void DockLayout::calculateHeaderAreas() {
}
}
ualni DockLayout::getVisibleSidesSize() {
ualni DockLayout::getVisibleSidesSize() const {
ualni out = 0;
for (ualni i = 0; i < 4; i++) {
if (isSideVisible(Side(i))) out++;

View file

@ -70,3 +70,7 @@ FloatingMenu::FloatingMenu() : FloatingWidget() {
// getLayout()->setLayoutPolicy(LayoutPolicy::Vertical);
// mBodyLayout.getLayout()->setLayoutPolicy(LayoutPolicy::Vertical);
}
void FloatingMenu::setText(const std::string& text) {
mHeader.setText(text);
}

View file

@ -20,6 +20,7 @@ namespace tp {
class WidgetLayout {
friend class DebugManager;
friend class LayoutManager;
public:
explicit WidgetLayout(Widget* widget) { mWidget = widget; }
@ -62,5 +63,8 @@ namespace tp {
Vec2<SizePolicy> mSizePolicy = { SizePolicy::Fixed, SizePolicy::Fixed };
Vec2F mMinSize = { 50, 50 };
Vec2F mMaxSize = { FLT_MAX / 2, FLT_MAX / 2 };
private:
// RectF mPrevArea{};
};
}

View file

@ -18,6 +18,8 @@ namespace tp {
void setRootWidget(Widget* widget);
static void setWidgetArea(Widget& widget, const RectF& rect);
[[nodiscard]] bool isDebug() const;
// Graphic Application Interface
public:
void processFrame(EventHandler* events, const RectF& screenArea);

View file

@ -39,11 +39,18 @@ namespace tp {
};
public:
Widget(const Widget&&) = delete;
Widget(const Widget&) = delete;
void operator=(const Widget&) = delete;
Widget();
virtual ~Widget();
void addChild(Widget* child, bool front = false);
void removeChild(Widget* child);
void clear();
const List<Widget*>& getChildren() { return mDepthOrder; }
void bringToFront();
void bringToBack();

View file

@ -0,0 +1,49 @@
#pragma once
#include "GraphicApplication.hpp"
#include "RootWidget.hpp"
#include "Timing.hpp"
namespace tp {
class WidgetApplication : public Application {
public:
WidgetApplication() = default;
void setRoot(Widget* widget) {
mRootWidget.setRootWidget(widget);
}
private:
void processFrame(EventHandler* eventHandler, halnf deltaTime) override {
const auto rec = RectF({ 0, 0 }, mWindow->getSize());
Timer timer;
mRootWidget.processFrame(eventHandler, rec);
mProcTime = timer.timePassed();
}
void drawFrame(Canvas* canvas) override {
Timer timer;
mRootWidget.drawFrame(*canvas);
mDrawTime = timer.timePassed();
if (mRootWidget.isDebug()) {
drawDebug();
debugUI();
}
}
bool forceNewFrame() override {
return mRootWidget.needsUpdate();
}
private:
void debugUI();
private:
time_ms mProcTime = 0;
time_ms mDrawTime = 0;
RootWidget mRootWidget;
};
}

View file

@ -17,7 +17,7 @@ namespace tp {
struct SideWidgetData {
Widget* widget = nullptr;
bool hidden = false;
halnf absoluteSize = 200;
halnf absoluteSize = 300;
alni order = -1;
Side side = { TOP };
@ -76,7 +76,7 @@ namespace tp {
const std::vector<Widget*>& getDockedWidgets();
private:
ualni getVisibleSidesSize();
ualni getVisibleSidesSize() const;
void calculateSideAreas();
void calculateResizeHandles();

View file

@ -27,6 +27,8 @@ namespace tp {
}
}
[[nodiscard]] bool isDebug() const { return mDebug; }
private:
void recursiveDraw(Canvas& canvas, Widget* active, const Vec2F& pos, int depthOrder);

View file

@ -39,6 +39,16 @@ namespace tp {
mContentWidget.addChild(widget);
}
const List<Widget*>& getContent() {
return mContentWidget.getChildren();
}
void clearChildren() {
mContentWidget.clear();
}
void setText(const std::string& text);
private:
// VerticalLayout mMenuLayout;
Widget mBodyLayout;

View file

@ -73,8 +73,10 @@ namespace tp {
[[nodiscard]] bool processesEvents() const override { return true; }
[[nodiscard]] bool needsNextFrame() const override { return mState != SLIDING; }
[[nodiscard]] halnf val() const { return mFactor; }
private:
RectF getHandleArea() const;
[[nodiscard]] RectF getHandleArea() const;
private:
halnf mFactor = 0;

View file

@ -1,17 +0,0 @@
project(WidgetsNew)
### ---------------------- Static Library --------------------- ###
file(GLOB SOURCES "./private/*.cpp" "./private/*/*.cpp")
file(GLOB HEADERS "./public/*.hpp")
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC ./public/ ./public/layouts ./public/mangers ./public/widgets)
target_link_libraries(${PROJECT_NAME} PUBLIC Math Graphics Imgui)
### -------------------------- Applications -------------------------- ###
add_executable(Widgets2Example examples/Example.cpp)
target_link_libraries(Widgets2Example ${PROJECT_NAME} ${GLEW_LIB})
target_include_directories(Widgets2Example PUBLIC ../Externals/glfw/include ${GLEW_INCLUDE_DIR})
file(COPY "examples/Font.ttf" DESTINATION "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/")