new widgets

This commit is contained in:
IlyaShurupov 2024-06-19 22:17:18 +03:00
parent 3dce41ea39
commit 8f62c8f387
18 changed files with 373 additions and 43 deletions

View file

@ -58,7 +58,7 @@ void Editor::loadDefaults() {
void Editor::setViewportSize(const Vec2F& size) { void Editor::setViewportSize(const Vec2F& size) {
// TODO remove // TODO remove
mScene.mCamera.rotate(0.01f, 0.0); // mScene.mCamera.rotate(0.01f, 0.0);
mScene.mRenderSettings.size = size; mScene.mRenderSettings.size = size;
@ -100,3 +100,19 @@ void Editor::denoisePathRenderBuffers() {
void Editor::setRenderType(Editor::RenderType type) { void Editor::setRenderType(Editor::RenderType type) {
mRenderType = type; mRenderType = type;
} }
void Editor::navigationOrbit(const Vec2F& delta) {
mScene.mCamera.rotate(delta.x, delta.y);
}
void Editor::navigationPan(const Vec2F& pos, const Vec2F& prevPos) {
mScene.mCamera.move(pos, prevPos);
}
void Editor::navigationZoom(halnf factor) {
mScene.mCamera.zoom(factor);
}
void Editor::navigationReset() {
mScene.mCamera.lookAtPoint({ 0, 0, 0 }, { 1, 5, 1 }, { 0, 0, 1 });
}

View file

@ -23,6 +23,12 @@ namespace tp {
void setRenderType(RenderType type); void setRenderType(RenderType type);
void denoisePathRenderBuffers(); void denoisePathRenderBuffers();
void navigationOrbit(const Vec2F& delta);
void navigationPan(const Vec2F& pos, const Vec2F& prevPos);
void navigationZoom(halnf factor);
void navigationReset();
private: private:
void sendBuffersToGPU(); void sendBuffersToGPU();
void denoise(); void denoise();

View file

@ -45,13 +45,36 @@ namespace tp {
this->mChildWidgets.pushBack(&mSplitView); this->mChildWidgets.pushBack(&mSplitView);
this->mChildWidgets.pushBack(&mSettingsWidget); this->mChildWidgets.pushBack(&mSettingsWidget);
mRenderPathTracer.mLabel.mLabel = "Render with Path Tracer"; // Render
mRenderRaster.mLabel.mLabel = "Render with Raster"; {
mDenoiseButton.mLabel.mLabel = "Denoise (IntelOpenImage)"; mRenderPathTracer.setLabel("Render with Path Tracer");
mRenderRaster.setLabel("Render with Raster");
mRenderDeNoise.setLabel("Denoise (IntelOpenImage)");
mSettingsWidget.addWidget(&mRenderPathTracer); mRenderMenu.addWidgetToMenu(&mRenderPathTracer);
mSettingsWidget.addWidget(&mRenderRaster); mRenderMenu.addWidgetToMenu(&mRenderRaster);
mSettingsWidget.addWidget(&mDenoiseButton); mRenderMenu.addWidgetToMenu(&mRenderDeNoise);
mRenderMenu.setLabel("Render");
}
// Navigation
{
mNavigationPan.setLabel("Pan");
mNavigationOrbit.setLabel("Orbit");
mNavigationZoom.setLabel("Zoom");
mNavigationReset.setLabel("Reset");
mNavigationMenu.addWidgetToMenu(&mNavigationPan);
mNavigationMenu.addWidgetToMenu(&mNavigationOrbit);
mNavigationMenu.addWidgetToMenu(&mNavigationZoom);
mNavigationMenu.addWidgetToMenu(&mNavigationReset);
mNavigationMenu.setLabel("Navigation");
}
mSettingsWidget.addWidget(&mRenderMenu);
mSettingsWidget.addWidget(&mNavigationMenu);
} }
void eventProcess(const Events& events) override { void eventProcess(const Events& events) override {
@ -60,17 +83,60 @@ namespace tp {
mViewport.setArea(mSplitView.getFirst()); mViewport.setArea(mSplitView.getFirst());
mSettingsWidget.setArea(mSplitView.getSecond()); mSettingsWidget.setArea(mSplitView.getSecond());
if (mRenderPathTracer.isFired()) { // render settings
mEditor->renderPathFrame(); {
mEditor->setRenderType(Editor::RenderType::PATH_TRACER); if (mRenderPathTracer.isFired()) {
mEditor->renderPathFrame();
mEditor->setRenderType(Editor::RenderType::PATH_TRACER);
}
if (mRenderRaster.isFired()) {
mEditor->setRenderType(Editor::RenderType::RASTER);
}
if (mRenderDeNoise.isFired()) {
mEditor->denoisePathRenderBuffers();
}
} }
if (mRenderRaster.isFired()) { // navigation
mEditor->setRenderType(Editor::RenderType::RASTER); {
} if (mNavigationOrbit.isFired()) {
mNavigationType = ORBIT;
}
if (mDenoiseButton.isFired()) { if (mNavigationPan.isFired()) {
mEditor->denoisePathRenderBuffers(); mNavigationType = PAN;
}
if (mNavigationZoom.isFired()) {
mNavigationType = ZOOM;
}
if (mNavigationReset.isFired()) {
mEditor->navigationReset();
}
const auto& activeArea = mViewport.mArea;
if (this->isHolding() && activeArea.isInside(events.getPointer())) {
switch (mNavigationType) {
case ORBIT:
mEditor->navigationOrbit(events.getPointerDelta() / activeArea.size * 3);
break;
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;
case ZOOM:
mEditor->navigationZoom(1 + (events.getPointerDelta().y / activeArea.size.y));
break;
}
}
} }
} }
@ -89,12 +155,22 @@ namespace tp {
SplitView<Events, Canvas> mSplitView; SplitView<Events, Canvas> mSplitView;
ViewportWidget<Events, Canvas> mViewport; ViewportWidget<Events, Canvas> mViewport;
ScrollableWindow<Events, Canvas> mSettingsWidget;
// Controls // Controls
ScrollableWindow<Events, Canvas> mSettingsWidget; CollapsableMenu<Events, Canvas> mRenderMenu;
ButtonWidget<Events, Canvas> mRenderPathTracer; ButtonWidget<Events, Canvas> mRenderPathTracer;
ButtonWidget<Events, Canvas> mRenderRaster; ButtonWidget<Events, Canvas> mRenderRaster;
ButtonWidget<Events, Canvas> mDenoiseButton; ButtonWidget<Events, Canvas> mRenderDeNoise;
// Navigation
enum NavigationType { ORBIT, PAN, ZOOM } mNavigationType = ORBIT;
CollapsableMenu<Events, Canvas> mNavigationMenu;
ButtonWidget<Events, Canvas> mNavigationPan;
ButtonWidget<Events, Canvas> mNavigationOrbit;
ButtonWidget<Events, Canvas> mNavigationZoom;
ButtonWidget<Events, Canvas> mNavigationReset;
RGBA mBaseColor; RGBA mBaseColor;
}; };

View file

@ -43,6 +43,7 @@ void EventHandler::processEvent() {
switch (eventData.type) { switch (eventData.type) {
case InputEvent::Type::MOUSE_POS: case InputEvent::Type::MOUSE_POS:
{ {
mPointerPrev = mPointer;
mPointer = eventData.mouseEvent; mPointer = eventData.mouseEvent;
mEventQueue.popFront(); mEventQueue.popFront();
break; break;
@ -77,6 +78,8 @@ void EventHandler::processEvent() {
const Vec2F& EventHandler::getPointer() const { return mPointer; } const Vec2F& EventHandler::getPointer() const { return mPointer; }
const Vec2F& EventHandler::getPointerPrev() const { return mPointerPrev; }
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;
} }
@ -92,4 +95,6 @@ bool EventHandler::isDown(InputID id) const {
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; }
Vec2F EventHandler::getPointerDelta() const { return mPointer - mPointerPrev; }

View file

@ -23,6 +23,17 @@ void Application::run() {
bool redrawNeeded = false; bool redrawNeeded = false;
// proc first frame by default
{
mWindow->processEvents();
processFrame(eventHandler);
mGraphics->drawBegin();
drawFrame(mGraphics->getCanvas());
mGraphics->drawEnd();
mWindow->draw();
}
while (!mWindow->shouldClose()) { while (!mWindow->shouldClose()) {
if (mProcTimer.isTimeout()) { if (mProcTimer.isTimeout()) {

View file

@ -70,6 +70,9 @@ namespace tp {
void processEvent(); void processEvent();
[[nodiscard]] const Vec2F& getPointer() const; [[nodiscard]] const Vec2F& getPointer() const;
[[nodiscard]] const Vec2F& getPointerPrev() const;
[[nodiscard]] Vec2F getPointerDelta() const;
[[nodiscard]] bool isPressed(InputID id) const; [[nodiscard]] bool isPressed(InputID id) const;
[[nodiscard]] bool isReleased(InputID id) const; [[nodiscard]] bool isReleased(InputID id) const;
[[nodiscard]] bool isDown(InputID id) const; [[nodiscard]] bool isDown(InputID id) const;
@ -85,6 +88,8 @@ namespace tp {
// input states // input states
Vec2F mPointer; Vec2F mPointer;
Vec2F mPointerPrev;
halnf mPointerPressure = 0; halnf mPointerPressure = 0;
InputState mInputStates[(int) InputID::LAST_KEY_CODE]{}; InputState mInputStates[(int) InputID::LAST_KEY_CODE]{};

View file

@ -12,7 +12,7 @@ namespace tp {
~Window(); ~Window();
public: public:
static Window* createWindow(Vec2F size = { 1000.f, 900.f }, const char* title = "Window"); static Window* createWindow(Vec2F size = { 500.f, 500.f }, const char* title = "Window");
static void destroyWindow(Window* window); static void destroyWindow(Window* window);
public: public:

View file

@ -30,9 +30,16 @@ namespace tp {
public: public:
void lookAtPoint(const Vec3F& aTarget, const Vec3F& aPos, Vec3F aUp); void lookAtPoint(const Vec3F& aTarget, const Vec3F& aPos, Vec3F aUp);
void rotate(halnf anglex, halnf angleY);
// -1 -1 is top left 1 1 is bottom right
void move(Vec2F aPos, Vec2F aPrevPos); void move(Vec2F aPos, Vec2F aPrevPos);
// keeps z axis above your head
void rotate(halnf anglex, halnf angleY);
// -1 -1 is top left 1 1 is bottom right
void zoom(halnf ratio); void zoom(halnf ratio);
void offset_target(halnf val); void offset_target(halnf val);
public: public:

View file

@ -159,6 +159,10 @@ namespace tp {
size = p3 - pos; size = p3 - pos;
} }
Rect<Type> shrink(Type val) const {
return { pos + val, size - val * 2 };
}
// if only one point isInside // if only one point isInside
bool clampOutside(Vec2<Type>& v1, Vec2<Type>& v2) { bool clampOutside(Vec2<Type>& v1, Vec2<Type>& v2) {
bool const in1 = isInside(v1); bool const in1 = isInside(v1);

View file

@ -34,6 +34,9 @@ void RasterRender::render(const Scene& geometry, const Vec2<ualni>& size) {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
// glPolygonMode(GL_FRONT, GL_LINE);
// glPolygonMode(GL_BACK, GL_LINE);
for (auto object : geometry.mObjects) { for (auto object : geometry.mObjects) {
static auto origin = (GLint) mDefaultShader.getu("Origin"); static auto origin = (GLint) mDefaultShader.getu("Origin");
@ -52,6 +55,10 @@ void RasterRender::render(const Scene& geometry, const Vec2<ualni>& size) {
mDefaultShader.unbind(); mDefaultShader.unbind();
// glPolygonMode(GL_FRONT, GL_FILL);
// glPolygonMode(GL_BACK, GL_FILL);
mRenderBuffer.endDraw(); mRenderBuffer.endDraw();
} }

View file

@ -1,16 +1,15 @@
#include "ChatGUI.hpp" #include "SimpleGUI.hpp"
#include "GraphicApplication.hpp" #include "GraphicApplication.hpp"
using namespace tp; using namespace tp;
class SimpleGUI : public Application { class SimpleGUI : public Application {
public: public:
SimpleGUI() { SimpleGUI() {
mGui.addWidget(&mButton);
mGui.addWidget(&mLabel);
mGui.addWidget(&mSlider);
} }
void processFrame(EventHandler* eventHandler) override { void processFrame(EventHandler* eventHandler) override {
@ -22,17 +21,14 @@ public:
} }
void drawFrame(Canvas* canvas) override { void drawFrame(Canvas* canvas) override {
canvas->rect(mGui.mArea, { 0, 0, 0, 1 }); canvas->rect(mGui.mArea, { 0.1f, 0.1f, 0.1f, 1.f });
mGui.drawWrapper(*canvas); mGui.drawWrapper(*canvas);
} }
private: private:
WidgetManager mWidgetManager; WidgetManager mWidgetManager;
ScrollableWindow<EventHandler, Canvas> mGui;
ButtonWidget<EventHandler, Canvas> mButton; SimpleWidget2<EventHandler, Canvas> mGui;
LabelWidget<EventHandler, Canvas> mLabel;
NamedSliderWidget<EventHandler, Canvas> mSlider;
}; };
int main() { int main() {

View file

@ -0,0 +1,45 @@
#include "Widgets.hpp"
namespace tp {
template <typename Events, typename Canvas>
class SimpleWidget : public ScrollableWindow<Events, Canvas> {
public:
SimpleWidget() {
this->addWidget(&mLabel);
this->addWidget(&mButton);
this->addWidget(&mSlider);
this->addWidget(&mCollapsableMenu);
mCollapsableMenu.addWidgetToMenu(&mInMenuButton1);
mCollapsableMenu.addWidgetToMenu(&mInMenuButton2);
mInMenuButton1.mLabel.mLabel = "Button1";
mInMenuButton2.mLabel.mLabel = "Button2";
this->mArea.size = { 500, 500 };
}
private:
CollapsableMenu<Events, Canvas> mCollapsableMenu;
ButtonWidget<EventHandler, Canvas> mInMenuButton1;
ButtonWidget<EventHandler, Canvas> mInMenuButton2;
ButtonWidget<EventHandler, Canvas> mButton;
LabelWidget<EventHandler, Canvas> mLabel;
NamedSliderWidget<EventHandler, Canvas> mSlider;
};
template <typename Events, typename Canvas>
class SimpleWidget2 : public Widget<Events, Canvas> {
public:
SimpleWidget2() {
this->mChildWidgets.pushBack(&mFloating);
mFloating.addWidgetToMenu(&mWidget);
}
private:
FloatingWidget<EventHandler, Canvas> mFloating;
SimpleWidget<EventHandler, Canvas> mWidget;
};
}

View file

@ -32,6 +32,10 @@ namespace tp {
} }
} }
void setLabel(const std::string& string) {
mLabel.mLabel = string;
}
public: public:
void eventUpdateConfiguration(WidgetManager& wm) override { void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("Button"); wm.setActiveId("Button");

View file

@ -0,0 +1,91 @@
#pragma once
#include "ScrollableWidget.hpp"
#include "ButtonWidget.hpp"
namespace tp {
template <typename Events, typename Canvas>
class CollapsableMenu : public Widget<Events, Canvas> {
public:
CollapsableMenu() {
this->mChildWidgets.pushBack(&mHeader);
this->mChildWidgets.pushBack(&mBody);
}
void eventProcess(const Events&) override {
if (mHeader.isReleased()) {
mCollapsed = !mCollapsed;
}
mHeader.setArea(getHeaderRect());
mBody.mEnable = !mCollapsed;
if (mCollapsed) {
this->mArea.size.y = headerHeight;
} else {
this->mArea.size.y = headerHeight + getBodyRect().size.y + mPadding * 2;
mBody.setArea(getBodyRect());
}
}
void eventDraw(Canvas& canvas) override {
canvas.rect(this->mArea, mBorderColor, rounding);
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
}
public:
void addWidgetToMenu(Widget<Events, Canvas>* widget) {
mBody.addWidget(widget);
}
void setLabel(const std::string& string) {
mHeader.mLabel = string;
}
private:
RectF getHeaderRect() {
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
return out.shrink(mPadding);
}
RectF getBodyRect() {
RectF out = { { this->mArea.pos.x, this->mArea.pos.y + headerHeight },
{ this->mArea.size.x, mBody.getContentSize() }
};
if (mBody.getContentSize()) {
out = out.shrink(mPadding);
out.size.y += mPadding * 2 + 1;
}
return out;
}
public:
void eventUpdateConfiguration(WidgetManager& wm) override {
wm.setActiveId("CollapsableMenu");
headerHeight = wm.getNumber("HeaderHeight", 35);
mMenuColor = wm.getColor("MenuColor", RGBA(0, 0, 0, 1.f));
rounding = wm.getNumber("Rounding", "Rounding");
mBorderColor = wm.getColor("BorderColor", RGBA(0.16, 0.16, 0.16, 1.f));
mBorderSize = wm.getNumber("BorderSize", 2.f);
mPadding = wm.getNumber("Padding", "Padding");
}
protected:
ScrollableWindow<Events, Canvas> mBody;
LabelWidget<Events, Canvas> mHeader;
RGBA mMenuColor;
RGBA mBorderColor;
halnf headerHeight = 30;
halnf rounding = 0;
halnf mBorderSize = 0;
halnf mPadding = 0;
bool mCollapsed = true;
};
}

View file

@ -0,0 +1,46 @@
#pragma once
#include "CollapsableMenu.hpp"
namespace tp {
template <typename Events, typename Canvas>
class FloatingWidget : public CollapsableMenu<Events, Canvas> {
public:
FloatingWidget() {
this->mArea = { 0, 0, 300, 300 };
}
virtual void procWrapper(const Events& events, const RectF& parentArea) override {
if (!this->mEnable) return;
this->checkVisibility(events, parentArea);
if (!this->mVisible) return;
this->checkFocus(events);
this->checkClicked(events);
mParentArea = parentArea;
this->eventProcess(events);
for (auto child : this->mChildWidgets) {
child->procWrapper(events, this->getArea());
}
}
void eventProcess(const Events& events) override {
CollapsableMenu<Events, Canvas>::eventProcess(events);
if (this->mHeader.isHolding()) {
this->mArea.pos += events.getPointerDelta();
if (!this->mArea.isEnclosedIn(mParentArea)) {
this->mArea.pos -= events.getPointerDelta();
}
}
}
RectF mParentArea;
};
}

View file

@ -6,10 +6,12 @@ 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() = default; LabelWidget() {
this->mArea = { 0, 0, 100, 30 };
}
void eventDraw(Canvas& canvas) override { void eventDraw(Canvas& canvas) override {
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor); canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::LC, padding, fontColor);
} }
public: public:

View file

@ -131,7 +131,7 @@ namespace tp {
this->mChildWidgets.pushBack(&mContentWidget); this->mChildWidgets.pushBack(&mContentWidget);
} }
~ScrollableWindow() = default; virtual ~ScrollableWindow() = default;
// takes whole area // takes whole area
void eventProcess(const Events& events) override { void eventProcess(const Events& events) override {
@ -154,7 +154,7 @@ namespace tp {
for (auto widget : content) { for (auto widget : content) {
widget->setArea({ mContentWidget.mArea.x + padding, widget->setArea({ mContentWidget.mArea.x + padding,
widget->mArea.y, mContentWidget.mArea.y + widget->mArea.y,
mScroller.getViewport().z - padding * 2, mScroller.getViewport().z - padding * 2,
widget->mArea.w }); widget->mArea.w });
} }
@ -169,23 +169,30 @@ namespace tp {
mPadding = wm.getNumber("Padding", "Padding"); mPadding = wm.getNumber("Padding", "Padding");
} }
[[nodiscard]] halnf getContentSize() const {
return mContentSize;
}
private: private:
void updateContents(List<Widget<Events, Canvas>*>& contentWidgets) { void updateContents(List<Widget<Events, Canvas>*>& contentWidgets) {
if (contentWidgets.size()) { if (!contentWidgets.size()) {
const halnf offset = contentWidgets.first()->mArea.y + mPadding; return;
}
halnf start = 0; const halnf offset = contentWidgets.first()->mArea.y + mPadding;
for (auto widget : contentWidgets) {
widget->mArea.y = start;
start += widget->mArea.w + mPadding;
}
for (auto widget : contentWidgets) { halnf start = 0;
widget->mArea.y += offset; for (auto widget : contentWidgets) {
} widget->mArea.y = start;
start += widget->mArea.w + mPadding;
}
for (auto widget : contentWidgets) {
widget->mArea.y += offset;
} }
} }
// ready content size
void updateContentSize(List<Widget<Events, Canvas>*>& contentWidgets) { void updateContentSize(List<Widget<Events, Canvas>*>& contentWidgets) {
mContentSize = 0; mContentSize = 0;
if (contentWidgets.size()) { if (contentWidgets.size()) {

View file

@ -6,4 +6,6 @@
#include "SplitViewWidget.hpp" #include "SplitViewWidget.hpp"
#include "TextInputWidget.hpp" #include "TextInputWidget.hpp"
#include "SliderWidget.hpp" #include "SliderWidget.hpp"
#include "CollapsableMenu.hpp"
#include "FloatingWidget.hpp"
#include "Animations.hpp" #include "Animations.hpp"