diff --git a/src/DrawVisitor.cpp b/src/DrawVisitor.cpp index 6b5f0ef..9d03a39 100644 --- a/src/DrawVisitor.cpp +++ b/src/DrawVisitor.cpp @@ -21,9 +21,12 @@ #include +#include "Decorations.h" #include "defines.h" -#include "DrawVisitor.h" #include "Scene.h" +#include "Primitives.h" + +#include "DrawVisitor.h" DrawVisitor::DrawVisitor(Node *nodetodraw, glm::mat4 projection, bool force): force_(force) @@ -115,3 +118,65 @@ void DrawVisitor::visit(Switch &n) void DrawVisitor::visit(Primitive &) { } + + + +ColorVisitor::ColorVisitor(glm::vec4 color): color_(color) +{ + +} +void ColorVisitor::visit(Node &) +{ +} + +void ColorVisitor::visit(Group &n) +{ + // traverse children + for (NodeSet::iterator node = n.begin(); node != n.end(); ++node) { + (*node)->accept(*this); + } +} + +void ColorVisitor::visit(Scene &n) +{ + n.root()->accept(*this); +} + +void ColorVisitor::visit(Switch &n) +{ + n.activeChild()->accept(*this); +} + +void ColorVisitor::visit(Primitive &p) +{ + p.shader()->color = color_; +} + +void ColorVisitor::visit(Frame &d) +{ + d.color = color_; +} + +void ColorVisitor::visit(Handles &d) +{ + d.color = color_; +} + +void ColorVisitor::visit(Symbol &d) +{ + d.color = color_; +} + +void ColorVisitor::visit(Disk &d) +{ + d.color = color_; +} + +void ColorVisitor::visit(Character &d) +{ + d.color = color_; +} + + + + diff --git a/src/DrawVisitor.h b/src/DrawVisitor.h index 356edba..b9c5b26 100644 --- a/src/DrawVisitor.h +++ b/src/DrawVisitor.h @@ -1,9 +1,16 @@ #ifndef DRAWVISITOR_H #define DRAWVISITOR_H -#include "GlmToolkit.h" +#include +#include #include "Visitor.h" +/// +/// \brief The DrawVisitor is typically called on a scene. +/// It traverses its root and draws only the nodes +/// listed in the constructor. The nodes listed must already +/// be in the hierarchy of the scene +/// class DrawVisitor : public Visitor { glm::mat4 modelview_; @@ -26,4 +33,31 @@ public: void visit(Switch& n) override; }; + +/// +/// \brief The ColorVisitor changes the colors of +/// all nodes that can draw (e.g. primitive, decorations) +/// to the given color +/// +class ColorVisitor : public Visitor +{ + glm::vec4 color_; + +public: + ColorVisitor(glm::vec4 color); + + void visit(Scene& n) override; + void visit(Node& n) override; + void visit(Group& n) override; + void visit(Switch& n) override; + + void visit(Primitive& ) override; + void visit(Frame& ) override; + void visit(Handles& ) override; + void visit(Symbol& ) override; + void visit(Disk& ) override; + void visit(Character& ) override; +}; + + #endif // DRAWVISITOR_H diff --git a/src/Primitives.cpp b/src/Primitives.cpp index d622b50..599946b 100644 --- a/src/Primitives.cpp +++ b/src/Primitives.cpp @@ -192,7 +192,7 @@ void Points::accept(Visitor& v) -HLine::HLine(float linewidth): Primitive(new Shader), width(linewidth) +HLine::HLine(float linewidth, Shader *s): Primitive(s), width(linewidth) { // 1 3 // +-------+ ^ @@ -216,9 +216,6 @@ HLine::HLine(float linewidth): Primitive(new Shader), width(linewidth) // default scale scale_.y = width; - - //default color - color = glm::vec4( 1.f, 1.f, 1.f, 1.f); } HLine::~HLine() @@ -271,13 +268,10 @@ void HLine::draw(glm::mat4 modelview, glm::mat4 projection) scale_.y = (float) width / vec.y; update(0); - // change color - shader_->color = color; - Primitive::draw(modelview, projection); } -VLine::VLine(float linewidth): Primitive(new Shader), width(linewidth) +VLine::VLine(float linewidth, Shader *s): Primitive(s), width(linewidth) { points_ = std::vector { glm::vec3( 0.f, -1.f, 0.f ), glm::vec3( 0.001f, -0.999f, 0.f ), @@ -293,9 +287,6 @@ VLine::VLine(float linewidth): Primitive(new Shader), width(linewidth) // default scale scale_.x = width; - - // default color - color = glm::vec4( 1.f, 1.f, 1.f, 1.f); } VLine::~VLine() @@ -348,45 +339,53 @@ void VLine::draw(glm::mat4 modelview, glm::mat4 projection) scale_.x = width / vec.x; update(0); - // change color - shader_->color = color; - Primitive::draw(modelview, projection); } LineSquare::LineSquare(float linewidth) : Group() { - top_ = new HLine(linewidth); + shader__ = new Shader; + + top_ = new HLine(linewidth, shader__); top_->translation_ = glm::vec3(0.f, 1.f, 0.f); attach(top_); - bottom_ = new HLine(linewidth); + bottom_ = new HLine(linewidth, shader__); bottom_->translation_ = glm::vec3(0.f, -1.f, 0.f); attach(bottom_); - left_ = new VLine(linewidth); + left_ = new VLine(linewidth, shader__); left_->translation_ = glm::vec3(-1.f, 0.f, 0.f); attach(left_); - right_ = new VLine(linewidth); + right_ = new VLine(linewidth, shader__); right_->translation_ = glm::vec3(1.f, 0.f, 0.f); attach(right_); } - LineSquare::LineSquare(const LineSquare &square) { - top_ = new HLine(square.top_->width); + shader__ = new Shader; + shader__->color = square.color(); + + top_ = new HLine(square.top_->width, shader__); top_->translation_ = glm::vec3(0.f, 1.f, 0.f); attach(top_); - bottom_ = new HLine(square.bottom_->width); + bottom_ = new HLine(square.bottom_->width, shader__); bottom_->translation_ = glm::vec3(0.f, -1.f, 0.f); attach(bottom_); - left_ = new VLine(square.left_->width); + left_ = new VLine(square.left_->width, shader__); left_->translation_ = glm::vec3(-1.f, 0.f, 0.f); attach(left_); - right_ = new VLine(square.right_->width); + right_ = new VLine(square.right_->width, shader__); right_->translation_ = glm::vec3(1.f, 0.f, 0.f); attach(right_); +} - setColor(square.color()); +LineSquare::~LineSquare() +{ + top_->replaceShader(nullptr); + bottom_->replaceShader(nullptr); + left_->replaceShader(nullptr); + right_->replaceShader(nullptr); + delete shader__; } void LineSquare::setLineWidth(float v) @@ -397,12 +396,74 @@ void LineSquare::setLineWidth(float v) right_->width = v; } -void LineSquare::setColor(glm::vec4 c) +LineGrid::LineGrid(size_t N, float step, float linewidth) { - top_->color = c; - bottom_->color = c; - left_->color = c; - right_->color = c; + shader__ = new Shader; + N = MAX(1, N); + + for (size_t n = 0; n < N ; ++n) { + VLine *l = new VLine(linewidth, shader__); + l->translation_.x = (float)n * step; + l->scale_.y = (float)N * step; + attach(l); + } + for (size_t n = 1; n < N ; ++n) { + VLine *l = new VLine(linewidth, shader__); + l->translation_.x = (float)n * -step; + l->scale_.y = (float)N * step; + attach(l); + } + for (size_t n = 0; n < N ; ++n) { + HLine *l = new HLine(linewidth, shader__); + l->translation_.y = (float)n * step; + l->scale_.x = (float)N * step; + attach(l); + } + for (size_t n = 1; n < N ; ++n) { + HLine *l = new HLine(linewidth, shader__); + l->translation_.y = (float)n * -step; + l->scale_.x = (float)N * step; + attach(l); + } +} + +LineGrid::~LineGrid() +{ + // prevent nodes from deleting the shader + for (NodeSet::iterator node = begin(); node != end(); ++node) { + Primitive *p = dynamic_cast(*node); + if (p) + p->replaceShader(nullptr); + } + delete shader__; +} + +void LineGrid::setLineWidth(float v) +{ + for (NodeSet::iterator node = begin(); node != end(); ++node) { + VLine *vl = dynamic_cast(*node); + if (vl) { + vl->width = v; + continue; + } + HLine *hl = dynamic_cast(*node); + if (hl) + hl->width = v; + } +} + +float LineGrid::lineWidth() const +{ + Node *n = front(); + if (n) { + VLine *vl = dynamic_cast(n); + if (vl) + return vl->width; + HLine *hl = dynamic_cast(n); + if (hl) + return hl->width; + } + return 0.f; } LineStrip::LineStrip(const std::vector &path, float linewidth) : Primitive(new Shader), diff --git a/src/Primitives.h b/src/Primitives.h index 055adb3..09786fe 100644 --- a/src/Primitives.h +++ b/src/Primitives.h @@ -108,13 +108,12 @@ class HLine : public Primitive { public: - HLine(float width = 1.f); + HLine(float width = 1.f, Shader *s = new Shader); virtual ~HLine(); void init () override; void draw(glm::mat4 modelview, glm::mat4 projection) override; - glm::vec4 color; float width; }; @@ -122,13 +121,12 @@ class VLine : public Primitive { public: - VLine(float width = 1.f); + VLine(float width = 1.f, Shader *s = new Shader); virtual ~VLine(); void init () override; void draw(glm::mat4 modelview, glm::mat4 projection) override; - glm::vec4 color; float width; }; @@ -137,18 +135,38 @@ public: */ class LineSquare : public Group { + Shader *shader__; HLine *top_, *bottom_; VLine *left_, *right_; public: LineSquare(float linewidth = 1.f); LineSquare(const LineSquare &square); + virtual ~LineSquare(); void setLineWidth(float v); inline float lineWidth() const { return top_->width; } - void setColor(glm::vec4 c); - inline glm::vec4 color() const { return top_->color; } + inline void setColor(glm::vec4 c) { shader__->color = c; } + inline glm::vec4 color() const { return shader__->color; } +}; + +/** + * @brief The Grid class is a group of NxN vertical and horizontal lines + */ +class LineGrid : public Group { + + Shader *shader__; + +public: + LineGrid(size_t N, float step, float linewidth = 1.f); + ~LineGrid(); + + void setLineWidth(float v); + float lineWidth() const; + + inline void setColor(glm::vec4 c) { shader__->color = c; } + inline glm::vec4 color() const { return shader__->color; } }; /** diff --git a/src/Scene.cpp b/src/Scene.cpp index 2582d6a..17b3138 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -230,10 +230,10 @@ void Primitive::replaceShader( Shader *newshader ) color = shader_->color; delete shader_; } - shader_ = newshader; shader_->iTransform = iTransform; shader_->color = color; } + shader_ = newshader; } // @@ -268,7 +268,6 @@ void Group::attach(Node *child) } } - void Group::sort() { // reorder list of nodes @@ -338,17 +337,17 @@ NodeSet::iterator Group::end() } -Node *Group::front() +Node *Group::front() const { if (!children_.empty()) - return *children_.rbegin(); + return *children_.crbegin(); return nullptr; } -Node *Group::back() +Node *Group::back() const { if (!children_.empty()) - return *children_.begin(); + return *children_.cbegin(); return nullptr; } diff --git a/src/Scene.h b/src/Scene.h index 6275113..a6dc012 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -178,8 +178,8 @@ public: void sort(); NodeSet::iterator begin(); NodeSet::iterator end(); - Node *front(); - Node *back(); + Node *front() const; + Node *back() const; protected: NodeSet children_;