From f0091f9e045ac27765a92b90cd19b89225696461 Mon Sep 17 00:00:00 2001 From: James Grogan Date: Mon, 5 Dec 2022 10:59:45 +0000 Subject: [PATCH] Simple drawing example. --- apps/notes_tk/CMakeLists.txt | 5 +- .../canvas/CanvasCommandSelectorView.cpp | 42 ++++++++++ .../canvas/CanvasCommandSelectorView.h | 24 ++++++ apps/notes_tk/canvas/CanvasDrawingArea.cpp | 54 ++++++++++++ apps/notes_tk/canvas/CanvasDrawingArea.h | 29 +++++++ apps/notes_tk/canvas/CanvasElements.h | 7 ++ apps/notes_tk/canvas/CanvasView.cpp | 38 +++++++-- apps/notes_tk/canvas/CanvasView.h | 7 +- apps/notes_tk/text_editor/TextEditorView.cpp | 6 +- apps/notes_tk/text_editor/TextEditorView.h | 1 - src/client/TabbedPanelWidget.cpp | 4 +- src/core/memory/SharedMemory.cpp | 70 ++++++++-------- src/core/memory/SharedMemory.h | 14 ++-- src/graphics/opengl/OpenGlMeshPainter.cpp | 1 + src/mesh/MeshPrimitives.cpp | 68 +++++++++++++++ src/mesh/MeshPrimitives.h | 3 + src/ui_elements/widgets/VerticalSpacer.cpp | 4 +- src/ui_elements/widgets/VerticalSpacer.h | 2 +- src/visual_elements/CMakeLists.txt | 7 +- src/visual_elements/GeometryNode.h | 19 ++++- .../basic_shapes/CircleNode.cpp | 83 +++++++++++++++++++ src/visual_elements/basic_shapes/CircleNode.h | 25 ++++++ src/visual_elements/basic_shapes/LineNode.cpp | 0 .../basic_shapes/LineNode.cppcd | 0 src/visual_elements/basic_shapes/LineNode.h | 0 .../{ => basic_shapes}/RectangleNode.cpp | 0 .../{ => basic_shapes}/RectangleNode.h | 5 +- 27 files changed, 450 insertions(+), 68 deletions(-) create mode 100644 apps/notes_tk/canvas/CanvasCommandSelectorView.cpp create mode 100644 apps/notes_tk/canvas/CanvasCommandSelectorView.h create mode 100644 apps/notes_tk/canvas/CanvasDrawingArea.cpp create mode 100644 apps/notes_tk/canvas/CanvasDrawingArea.h create mode 100644 apps/notes_tk/canvas/CanvasElements.h create mode 100644 src/visual_elements/basic_shapes/CircleNode.cpp create mode 100644 src/visual_elements/basic_shapes/CircleNode.h create mode 100644 src/visual_elements/basic_shapes/LineNode.cpp create mode 100644 src/visual_elements/basic_shapes/LineNode.cppcd create mode 100644 src/visual_elements/basic_shapes/LineNode.h rename src/visual_elements/{ => basic_shapes}/RectangleNode.cpp (100%) rename src/visual_elements/{ => basic_shapes}/RectangleNode.h (96%) diff --git a/apps/notes_tk/CMakeLists.txt b/apps/notes_tk/CMakeLists.txt index f43ebc5..c290c63 100644 --- a/apps/notes_tk/CMakeLists.txt +++ b/apps/notes_tk/CMakeLists.txt @@ -13,12 +13,13 @@ list(APPEND client_HEADERS image_editor/ImageViewWidget.h canvas/CanvasView.h canvas/CanvasController.h + canvas/CanvasDrawingArea.h + canvas/CanvasCommandSelectorView.h mesh_viewer/MeshViewerView.h mesh_viewer/MeshViewerController.h mesh_viewer/MeshViewerCanvas.h web_client/WebClientView.h) - list(APPEND client_LIB_INCLUDES text_editor/TextEditorView.cpp text_editor/TextEditorModel.cpp @@ -32,6 +33,8 @@ list(APPEND client_LIB_INCLUDES mesh_viewer/MeshViewerCanvas.cpp canvas/CanvasView.cpp canvas/CanvasController.cpp + canvas/CanvasDrawingArea.cpp + canvas/CanvasCommandSelectorView.cpp web_client/WebClientView.cpp NotesTk.cpp) diff --git a/apps/notes_tk/canvas/CanvasCommandSelectorView.cpp b/apps/notes_tk/canvas/CanvasCommandSelectorView.cpp new file mode 100644 index 0000000..78e1ca8 --- /dev/null +++ b/apps/notes_tk/canvas/CanvasCommandSelectorView.cpp @@ -0,0 +1,42 @@ +#include "CanvasCommandSelectorView.h" + +#include "HorizontalSpacer.h" +#include "Button.h" +#include "Theme.h" + +CanvasCommandSelectorView::CanvasCommandSelectorView() + : Widget() +{ + auto circle_button = Button::Create(); + + auto on_circle_click = [this](Widget* self){ + onCommandSelected(CanvasDrawCommand::CIRCLE); + }; + circle_button->setLabel("Circle"); + circle_button->setBackgroundColor(Theme::getButtonPrimaryBackground()); + circle_button->setMargin(2); + circle_button->setOnClickFunction(on_circle_click); + + auto on_line_click = [this](Widget* self){ + onCommandSelected(CanvasDrawCommand::LINE); + }; + auto line_button = Button::Create(); + line_button->setLabel("Line"); + line_button->setBackgroundColor(Theme::getButtonPrimaryBackground()); + line_button->setMargin(2); + line_button->setOnClickFunction(on_line_click); + + auto hspacer = HorizontalSpacer::Create(); + hspacer->addWidgetWithScale(std::move(circle_button), 1); + hspacer->addWidgetWithScale(std::move(line_button), 1); + + addWidget(std::move(hspacer)); +} + +void CanvasCommandSelectorView::onCommandSelected(CanvasDrawCommand command) +{ + if(mCommandSelectedCallback) + { + mCommandSelectedCallback(command); + } +} diff --git a/apps/notes_tk/canvas/CanvasCommandSelectorView.h b/apps/notes_tk/canvas/CanvasCommandSelectorView.h new file mode 100644 index 0000000..ffb6ece --- /dev/null +++ b/apps/notes_tk/canvas/CanvasCommandSelectorView.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Widget.h" +#include "CanvasElements.h" + +#include + +class CanvasCommandSelectorView : public Widget +{ +public: + + using onCommandSelectedFunc = std::function; + CanvasCommandSelectorView(); + + void setCommandSelectedCallback(onCommandSelectedFunc func) + { + mCommandSelectedCallback = func; + } + + void onCommandSelected(CanvasDrawCommand command); + +private: + onCommandSelectedFunc mCommandSelectedCallback{nullptr}; +}; diff --git a/apps/notes_tk/canvas/CanvasDrawingArea.cpp b/apps/notes_tk/canvas/CanvasDrawingArea.cpp new file mode 100644 index 0000000..65cb432 --- /dev/null +++ b/apps/notes_tk/canvas/CanvasDrawingArea.cpp @@ -0,0 +1,54 @@ +#include "CanvasDrawingArea.h" + +#include "MouseEvent.h" + +#include "GeometryNode.h" +#include "TransformNode.h" +#include "CircleNode.h" + +#include + +CanvasDrawingArea::~CanvasDrawingArea() +{ + +} + +void CanvasDrawingArea::addShapeAt(unsigned x, unsigned y) +{ + if (mActiveDrawingCommand == CanvasDrawCommand::CIRCLE) + { + auto circle = std::make_unique(DiscretePoint(x, y), 5); + circle->setFillColor(Color(255, 0, 0)); + circle->setName("CanvasDrawingArea_CircleNode"); + + mRootNode->addChild(circle.get()); + + mSceneNodes.push_back(std::move(circle)); + mContentDirty = true; + } +} + +bool CanvasDrawingArea::isDirty() const +{ + return Widget::isDirty() || mContentDirty; +} + +void CanvasDrawingArea::doPaint(const PaintEvent* event) +{ + mContentDirty = false; +} + +void CanvasDrawingArea::onMyMouseEvent(const MouseEvent* event) +{ + if(event->GetAction() == MouseEvent::Action::Pressed) + { + + } + else if(event->GetAction() == MouseEvent::Action::Released) + { + auto client_loc = event->GetClientLocation(); + auto screen_loc = event->GetScreenLocation(); + + addShapeAt(client_loc.GetX(), client_loc.GetY()); + } +} diff --git a/apps/notes_tk/canvas/CanvasDrawingArea.h b/apps/notes_tk/canvas/CanvasDrawingArea.h new file mode 100644 index 0000000..c42034e --- /dev/null +++ b/apps/notes_tk/canvas/CanvasDrawingArea.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Widget.h" +#include "CanvasElements.h" + +class GeometryNode; + +class CanvasDrawingArea : public Widget +{ +public: + ~CanvasDrawingArea(); + void setActiveDrawingCommand(CanvasDrawCommand command) + { + mActiveDrawingCommand = command; + } + +private: + bool isDirty() const override; + void doPaint(const PaintEvent* event) override; + + void onMyMouseEvent(const MouseEvent* event) override; + + void addShapeAt(unsigned x, unsigned y); + + CanvasDrawCommand mActiveDrawingCommand{CanvasDrawCommand::LINE}; + + std::vector > mSceneNodes; + bool mContentDirty{false}; +}; diff --git a/apps/notes_tk/canvas/CanvasElements.h b/apps/notes_tk/canvas/CanvasElements.h new file mode 100644 index 0000000..2127189 --- /dev/null +++ b/apps/notes_tk/canvas/CanvasElements.h @@ -0,0 +1,7 @@ +#pragma once + +enum class CanvasDrawCommand +{ + CIRCLE, + LINE +}; diff --git a/apps/notes_tk/canvas/CanvasView.cpp b/apps/notes_tk/canvas/CanvasView.cpp index c8fbc6e..47aa5ca 100644 --- a/apps/notes_tk/canvas/CanvasView.cpp +++ b/apps/notes_tk/canvas/CanvasView.cpp @@ -4,15 +4,16 @@ #include "VerticalSpacer.h" #include "CanvasController.h" +#include "CanvasDrawingArea.h" +#include "CanvasCommandSelectorView.h" #include "Theme.h" - #include "TextNode.h" +#include "GeometryNode.h" + #include "Label.h" #include "Button.h" -#include - CanvasView::CanvasView() : mController(CanvasController::Create()) { @@ -36,11 +37,28 @@ void CanvasView::initialize() label->setBackgroundColor(Theme::getBannerBackground()); label->setMargin(1); + auto controls = std::make_unique(); + controls->setBackgroundColor(Theme::getBannerBackground()); + controls->setMargin(1); + auto on_draw_command_changed = [this](CanvasDrawCommand command){ + onDrawCommandChanged(command); + }; + controls->setCommandSelectedCallback(on_draw_command_changed); + + auto drawing_area = std::make_unique(); + drawing_area->setBackgroundColor(Theme::getBackgroundPrimary()); + drawing_area->setMargin(1); + mDrawingArea = drawing_area.get(); + + auto control_draw_vspacer = VerticalSpacer::Create(); + control_draw_vspacer->addWidgetWithScale(std::move(controls), 1); + control_draw_vspacer->addWidgetWithScale(std::move(drawing_area), 10); auto hSpacer = HorizontalSpacer::Create(); hSpacer->addWidgetWithScale(std::move(label), 1); - //hSpacer->addWidgetWithScale(std::move(textBox), 14); + + hSpacer->addWidgetWithScale(std::move(control_draw_vspacer), 10); auto cache_button_spacer = initializeCacheButtons(); hSpacer->addWidgetWithScale(std::move(cache_button_spacer), 1); @@ -48,6 +66,11 @@ void CanvasView::initialize() addWidget(std::move(hSpacer)); } +void CanvasView::onDrawCommandChanged(CanvasDrawCommand command) +{ + mDrawingArea->setActiveDrawingCommand(command); +} + std::unique_ptr CanvasView::initializeCacheButtons() { auto saveButton = Button::Create(); @@ -66,10 +89,9 @@ std::unique_ptr CanvasView::initializeCacheButtons() loadButton->setMargin(2); auto buttonSpacer = VerticalSpacer::Create(); - buttonSpacer->AddWidgetWithScale(std::move(saveButton), 1); - buttonSpacer->AddWidgetWithScale(std::move(clearButton), 1); - buttonSpacer->AddWidgetWithScale(std::move(loadButton), 1); - + buttonSpacer->addWidgetWithScale(std::move(saveButton), 1); + buttonSpacer->addWidgetWithScale(std::move(clearButton), 1); + buttonSpacer->addWidgetWithScale(std::move(loadButton), 1); return buttonSpacer; } diff --git a/apps/notes_tk/canvas/CanvasView.h b/apps/notes_tk/canvas/CanvasView.h index ddc4c3e..f845f2d 100644 --- a/apps/notes_tk/canvas/CanvasView.h +++ b/apps/notes_tk/canvas/CanvasView.h @@ -1,8 +1,10 @@ #pragma once #include "Widget.h" +#include "CanvasElements.h" class CanvasController; +class CanvasDrawingArea; class CanvasView : public Widget { @@ -14,13 +16,14 @@ public: static std::unique_ptr Create(); private: + void onDrawCommandChanged(CanvasDrawCommand command); void initialize(); std::unique_ptr initializeCacheButtons(); - //std::unique_ptr initializeCacheButtons(); - std::unique_ptr mController; + + CanvasDrawingArea* mDrawingArea{nullptr}; }; using CanvasViewPtr = std::unique_ptr; diff --git a/apps/notes_tk/text_editor/TextEditorView.cpp b/apps/notes_tk/text_editor/TextEditorView.cpp index 26e322c..c8aa141 100644 --- a/apps/notes_tk/text_editor/TextEditorView.cpp +++ b/apps/notes_tk/text_editor/TextEditorView.cpp @@ -72,9 +72,9 @@ void TextEditorView::initialize() loadButton->setOnClickFunction(onLoad); auto buttonSpacer = VerticalSpacer::Create(); - buttonSpacer->AddWidgetWithScale(std::move(saveButton), 1); - buttonSpacer->AddWidgetWithScale(std::move(clearButton), 1); - buttonSpacer->AddWidgetWithScale(std::move(loadButton), 1); + buttonSpacer->addWidgetWithScale(std::move(saveButton), 1); + buttonSpacer->addWidgetWithScale(std::move(clearButton), 1); + buttonSpacer->addWidgetWithScale(std::move(loadButton), 1); auto hSpacer = HorizontalSpacer::Create(); hSpacer->addWidgetWithScale(std::move(label), 1); diff --git a/apps/notes_tk/text_editor/TextEditorView.h b/apps/notes_tk/text_editor/TextEditorView.h index 57aae3d..40546da 100644 --- a/apps/notes_tk/text_editor/TextEditorView.h +++ b/apps/notes_tk/text_editor/TextEditorView.h @@ -11,7 +11,6 @@ class TextEditorView : public Widget { public: - TextEditorView(); static std::unique_ptr Create(); diff --git a/src/client/TabbedPanelWidget.cpp b/src/client/TabbedPanelWidget.cpp index 6fda26d..3a312cd 100644 --- a/src/client/TabbedPanelWidget.cpp +++ b/src/client/TabbedPanelWidget.cpp @@ -17,8 +17,8 @@ TabbedPanelWidget::TabbedPanelWidget() nav->setSize({0, 0, 0, 0, 200, 0}); auto vertSpacer = VerticalSpacer::Create(); - vertSpacer->AddWidgetWithScale(std::move(nav), 1); - vertSpacer->AddWidgetWithScale(std::move(stack), 4); + vertSpacer->addWidgetWithScale(std::move(nav), 1); + vertSpacer->addWidgetWithScale(std::move(stack), 4); addWidget(std::move(vertSpacer)); } diff --git a/src/core/memory/SharedMemory.cpp b/src/core/memory/SharedMemory.cpp index 0be9dd1..d15b525 100644 --- a/src/core/memory/SharedMemory.cpp +++ b/src/core/memory/SharedMemory.cpp @@ -12,63 +12,63 @@ void SharedMemory::allocate(const std::string& namePrefix, std::size_t size) { - createFile(namePrefix); + createFile(namePrefix); - if (!mIsValid) - { - return; - } + if (!mIsValid) + { + return; + } #ifdef __linux__ - int ret{-1}; - do { - ret = ftruncate(mFileDescriptor, size); - } while (ret < 0 && errno == EINTR); + int ret{-1}; + do { + ret = ftruncate(mFileDescriptor, size); + } while (ret < 0 && errno == EINTR); - if (ret < 0) - { - close(mFileDescriptor); - mIsValid = false; - } + if (ret < 0) + { + close(mFileDescriptor); + mIsValid = false; + } #endif } int SharedMemory::getFileDescriptor() const { - return mFileDescriptor; + return mFileDescriptor; } bool SharedMemory::isValid() const { - return mIsValid; + return mIsValid; } void SharedMemory::createFile(const std::string& namePrefix) { #ifdef __linux__ - unsigned retries = 100; - do { - const auto name = getRandomName(namePrefix); - --retries; + unsigned retries = 100; + do { + const auto name = getRandomName(namePrefix); + --retries; - const int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) - { - shm_unlink(name.c_str()); - mFileDescriptor = fd; - mIsValid = true; - break; - } - } while (retries > 0 && errno == EEXIST); + const int fd = shm_open(name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) + { + shm_unlink(name.c_str()); + mFileDescriptor = fd; + mIsValid = true; + break; + } + } while (retries > 0 && errno == EEXIST); #endif } std::string SharedMemory::getRandomName(const std::string& namePrefix) const { - std::string randomSuffix; - for (const auto entry : RandomUtils::getRandomVecUnsigned(6)) - { - randomSuffix += std::to_string(entry); - } - return namePrefix + randomSuffix; + std::string randomSuffix; + for (const auto entry : RandomUtils::getRandomVecUnsigned(6)) + { + randomSuffix += std::to_string(entry); + } + return namePrefix + randomSuffix; } diff --git a/src/core/memory/SharedMemory.h b/src/core/memory/SharedMemory.h index 333d6b6..d483438 100644 --- a/src/core/memory/SharedMemory.h +++ b/src/core/memory/SharedMemory.h @@ -5,18 +5,18 @@ class SharedMemory { public: - void allocate(const std::string& namePrefix, std::size_t size); + void allocate(const std::string& namePrefix, std::size_t size); - int getFileDescriptor() const; + int getFileDescriptor() const; - bool isValid() const; + bool isValid() const; private: - void createFile(const std::string& namePrefix); + void createFile(const std::string& namePrefix); - std::string getRandomName(const std::string& namePrefix) const; + std::string getRandomName(const std::string& namePrefix) const; - int mFileDescriptor{0}; - bool mIsValid{false}; + int mFileDescriptor{0}; + bool mIsValid{false}; }; diff --git a/src/graphics/opengl/OpenGlMeshPainter.cpp b/src/graphics/opengl/OpenGlMeshPainter.cpp index 68a7b3c..098d300 100644 --- a/src/graphics/opengl/OpenGlMeshPainter.cpp +++ b/src/graphics/opengl/OpenGlMeshPainter.cpp @@ -110,6 +110,7 @@ void OpenGlMeshPainter::paint(SceneModel* model, DrawingContext* context) auto y = vertices[idx]*transform.getScaleY() + transform.getLocation().getY(); vertices[idx] = 1.0 - 2*y/height; } + } std::vector indices; diff --git a/src/mesh/MeshPrimitives.cpp b/src/mesh/MeshPrimitives.cpp index fd79701..ebe8fe9 100644 --- a/src/mesh/MeshPrimitives.cpp +++ b/src/mesh/MeshPrimitives.cpp @@ -32,6 +32,74 @@ std::unique_ptr MeshPrimitives::buildRectangleAsTriMesh() return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } +std::unique_ptr MeshPrimitives::buildCircleAsTriMesh(unsigned numSegments) +{ + VecPoints locations(numSegments + 1); + locations[0] = {0, 0}; + + const double delta_theta = (2.0*M_PI)/double(numSegments); + double theta = 0.0; + for(unsigned idx=1; idx<=numSegments; idx++) + { + const double x = sin(theta); + const double y = cos(theta); + locations[idx] = {x, y}; + theta += delta_theta; + } + + EdgeIds edge_ids(2*numSegments); + for(unsigned idx=0; idx numSegments) + { + wrap_node = 1; + } + edge_ids[idx + numSegments] = {idx + 1, wrap_node}; + } + + FaceIds face_ids(numSegments); + for(unsigned idx=0; idx MeshPrimitives::buildCircleAsLineMesh(unsigned numSegments) +{ + VecPoints locations(numSegments); + const double delta_theta = (2.0*M_PI)/double(numSegments); + double theta = 0.0; + for(unsigned idx=0; idx MeshPrimitives::buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio, unsigned num_segments) { unsigned num_fans = 4; diff --git a/src/mesh/MeshPrimitives.h b/src/mesh/MeshPrimitives.h index 6c87c43..a501526 100644 --- a/src/mesh/MeshPrimitives.h +++ b/src/mesh/MeshPrimitives.h @@ -6,6 +6,9 @@ class MeshPrimitives { public: + static std::unique_ptr buildCircleAsTriMesh(unsigned numSegments = 24); + + static std::unique_ptr buildCircleAsLineMesh(unsigned numSegments = 24); static std::unique_ptr buildRectangleAsTriMesh(); diff --git a/src/ui_elements/widgets/VerticalSpacer.cpp b/src/ui_elements/widgets/VerticalSpacer.cpp index 8b567df..3397987 100644 --- a/src/ui_elements/widgets/VerticalSpacer.cpp +++ b/src/ui_elements/widgets/VerticalSpacer.cpp @@ -17,10 +17,10 @@ std::unique_ptr VerticalSpacer::Create() void VerticalSpacer::addWidget(WidgetUPtr widget) { - AddWidgetWithScale(std::move(widget), 1.0); + addWidgetWithScale(std::move(widget), 1.0); } -void VerticalSpacer::AddWidgetWithScale(WidgetUPtr widget, double scale) +void VerticalSpacer::addWidgetWithScale(WidgetUPtr widget, double scale) { Widget::addWidget(std::move(widget)); mScales.push_back(scale); diff --git a/src/ui_elements/widgets/VerticalSpacer.h b/src/ui_elements/widgets/VerticalSpacer.h index 66f0cc3..069b505 100644 --- a/src/ui_elements/widgets/VerticalSpacer.h +++ b/src/ui_elements/widgets/VerticalSpacer.h @@ -12,7 +12,7 @@ public: void addWidget(WidgetUPtr widget) override; - void AddWidgetWithScale(WidgetUPtr widget, double scale); + void addWidgetWithScale(WidgetUPtr widget, double scale); private: void updateChildLocations() override; diff --git a/src/visual_elements/CMakeLists.txt b/src/visual_elements/CMakeLists.txt index dacad19..974b7e4 100644 --- a/src/visual_elements/CMakeLists.txt +++ b/src/visual_elements/CMakeLists.txt @@ -1,6 +1,8 @@ list(APPEND visual_elements_LIB_INCLUDES GeometryNode.cpp - RectangleNode.cpp + basic_shapes/RectangleNode.cpp + basic_shapes/CircleNode.cpp + basic_shapes/LineNode.cpp MaterialNode.cpp MeshNode.cpp TextNode.cpp @@ -17,7 +19,8 @@ list(APPEND visual_elements_LIB_INCLUDES add_library(visual_elements SHARED ${visual_elements_LIB_INCLUDES}) target_include_directories(visual_elements PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/basic_shapes ) target_link_libraries(visual_elements PUBLIC core geometry fonts mesh image) diff --git a/src/visual_elements/GeometryNode.h b/src/visual_elements/GeometryNode.h index 0187ee6..f060bb6 100644 --- a/src/visual_elements/GeometryNode.h +++ b/src/visual_elements/GeometryNode.h @@ -10,7 +10,9 @@ public: Path, Rectangle, Circle, - Arc + Arc, + Line, + Polyline }; public: @@ -29,4 +31,19 @@ protected: bool mGeometryIsDirty{true}; }; +class LineNode : public GeometryNode +{ +public: + LineNode(const DiscretePoint& location) + : GeometryNode(location) + { + + } + + Type getType() + { + return Type::Line; + } +}; + using GeometryNodePtr = std::unique_ptr; diff --git a/src/visual_elements/basic_shapes/CircleNode.cpp b/src/visual_elements/basic_shapes/CircleNode.cpp new file mode 100644 index 0000000..7ebf4fd --- /dev/null +++ b/src/visual_elements/basic_shapes/CircleNode.cpp @@ -0,0 +1,83 @@ +#include "CircleNode.h" + +#include "FontsManager.h" +#include "SceneModel.h" +#include "AbstractMesh.h" +#include "MeshPrimitives.h" + +#include + +CircleNode::CircleNode(const DiscretePoint& location, unsigned radius) +: GeometryNode(location), + mRadius(radius) +{ + +} + +CircleNode::Type CircleNode::getType() +{ + return Type::Circle; +} + +unsigned CircleNode::getRadius() const +{ + return mRadius; +} + +SceneItem* CircleNode::getSceneItem(std::size_t idx) const +{ + if (idx == 0) + { + return mBackgroundItem.get(); + } + else + { + return nullptr; + } +} + +unsigned CircleNode::getNumSceneItems() const +{ + return 1; +} + +void CircleNode::setRadius(unsigned radius) +{ + if (mRadius != radius) + { + mRadius = radius; + mTransformIsDirty = true; + } + +} + +void CircleNode::update(FontsManager* fontsManager) +{ + if (!mBackgroundItem || mGeometryIsDirty) + { + auto mesh = MeshPrimitives::buildCircleAsTriMesh(); + + if (!mBackgroundItem) + { + mBackgroundItem = std::make_unique(std::move(mesh)); + mBackgroundItem->setName(mName + "_Model"); + } + else + { + mBackgroundItem->updateMesh(std::move(mesh)); + } + mGeometryIsDirty = false; + } + + if (mTransformIsDirty) + { + mBackgroundItem->updateTransform({mLocation, static_cast(2*mRadius), static_cast(2*mRadius)}); + mTransformIsDirty = false; + } + + if (mMaterialIsDirty) + { + mBackgroundItem->updateUniformColor(mFillColor); + mMaterialIsDirty = false; + } +} diff --git a/src/visual_elements/basic_shapes/CircleNode.h b/src/visual_elements/basic_shapes/CircleNode.h new file mode 100644 index 0000000..a31a47a --- /dev/null +++ b/src/visual_elements/basic_shapes/CircleNode.h @@ -0,0 +1,25 @@ +#pragma once + +#include "GeometryNode.h" + +class CircleNode : public GeometryNode +{ +public: + CircleNode(const DiscretePoint& location, unsigned radius); + + Type getType(); + + unsigned getRadius() const; + + SceneItem* getSceneItem(std::size_t idx) const override; + unsigned getNumSceneItems() const override; + + void setRadius(unsigned radius); + + void update(FontsManager* fontsManager) override; +private: + unsigned mRadius{1}; + + std::unique_ptr mBackgroundItem; + std::unique_ptr mOutlineItem; +}; diff --git a/src/visual_elements/basic_shapes/LineNode.cpp b/src/visual_elements/basic_shapes/LineNode.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/visual_elements/basic_shapes/LineNode.cppcd b/src/visual_elements/basic_shapes/LineNode.cppcd new file mode 100644 index 0000000..e69de29 diff --git a/src/visual_elements/basic_shapes/LineNode.h b/src/visual_elements/basic_shapes/LineNode.h new file mode 100644 index 0000000..e69de29 diff --git a/src/visual_elements/RectangleNode.cpp b/src/visual_elements/basic_shapes/RectangleNode.cpp similarity index 100% rename from src/visual_elements/RectangleNode.cpp rename to src/visual_elements/basic_shapes/RectangleNode.cpp diff --git a/src/visual_elements/RectangleNode.h b/src/visual_elements/basic_shapes/RectangleNode.h similarity index 96% rename from src/visual_elements/RectangleNode.h rename to src/visual_elements/basic_shapes/RectangleNode.h index 554f6ba..21d5788 100644 --- a/src/visual_elements/RectangleNode.h +++ b/src/visual_elements/basic_shapes/RectangleNode.h @@ -1,9 +1,8 @@ #pragma once -#include - #include "GeometryNode.h" -#include "DiscretePoint.h" + +#include class RectangleNode : public GeometryNode {