Convert visual layers to scene nodes.

This commit is contained in:
James Grogan 2022-11-16 15:06:08 +00:00
parent 798cb365d7
commit 3e53bd9e00
64 changed files with 863 additions and 551 deletions

View file

@ -6,6 +6,7 @@
#include "WebClientView.h" #include "WebClientView.h"
#include "TabbedPanelWidget.h" #include "TabbedPanelWidget.h"
#include "TopBar.h" #include "TopBar.h"
#include "TextNode.h"
#include "StatusBar.h" #include "StatusBar.h"
#include "HorizontalSpacer.h" #include "HorizontalSpacer.h"

View file

@ -2,6 +2,7 @@
#include "Label.h" #include "Label.h"
#include "Color.h" #include "Color.h"
#include "TextNode.h"
AudioEditorView::AudioEditorView() AudioEditorView::AudioEditorView()
{ {

View file

@ -2,6 +2,7 @@
#include "Label.h" #include "Label.h"
#include "Color.h" #include "Color.h"
#include "TextNode.h"
ImageEditorView::ImageEditorView() ImageEditorView::ImageEditorView()
{ {

View file

@ -1,6 +1,8 @@
#include "HorizontalSpacer.h" #include "HorizontalSpacer.h"
#include "TextEditorView.h" #include "TextEditorView.h"
#include "VerticalSpacer.h" #include "VerticalSpacer.h"
#include "TextNode.h"
#include <iostream> #include <iostream>
TextEditorView::TextEditorView() TextEditorView::TextEditorView()

View file

@ -2,6 +2,7 @@
#include "Label.h" #include "Label.h"
#include "Color.h" #include "Color.h"
#include "TextNode.h"
WebClientView::WebClientView() WebClientView::WebClientView()
{ {

View file

@ -2,6 +2,7 @@
#include "StackWidget.h" #include "StackWidget.h"
#include "HorizontalSpacer.h" #include "HorizontalSpacer.h"
#include "VerticalSpacer.h" #include "VerticalSpacer.h"
#include "TextNode.h"
#include "Button.h" #include "Button.h"
TabbedPanelWidget::TabbedPanelWidget() TabbedPanelWidget::TabbedPanelWidget()

View file

@ -9,7 +9,7 @@ class Point
{ {
public: public:
Point(double x, double y, double z = 0); Point(double x = 0, double y = 0, double z = 0);
Point(const DiscretePoint& point); Point(const DiscretePoint& point);
@ -33,6 +33,17 @@ public:
double getDeltaY(const Point& point) const; double getDeltaY(const Point& point) const;
bool operator==(const Point& rhs) const
{
return (mX == rhs.mX)
&& (mY == rhs.mY)
&& (mZ == rhs.mZ);
}
bool operator!=(const Point& rhs) const
{
return !operator==(rhs);
}
private: private:
double mX{0}; double mX{0};
double mY{0}; double mY{0};

View file

@ -12,7 +12,6 @@
DrawingContext::DrawingContext(DrawingSurface* surface, FontsManager* fontsManager, DrawingMode requestedDrawingMode) DrawingContext::DrawingContext(DrawingSurface* surface, FontsManager* fontsManager, DrawingMode requestedDrawingMode)
: mSurface(surface), : mSurface(surface),
mDrawingMode(requestedDrawingMode), mDrawingMode(requestedDrawingMode),
mScene(std::make_unique<Scene>()),
mFontsManager(fontsManager) mFontsManager(fontsManager)
{ {
mPainter = PainterFactory::Create(mDrawingMode); mPainter = PainterFactory::Create(mDrawingMode);
@ -23,11 +22,6 @@ std::unique_ptr<DrawingContext> DrawingContext::Create(DrawingSurface* surface,
return std::make_unique<DrawingContext>(surface, fontsManager, requestedDrawingMode); return std::make_unique<DrawingContext>(surface, fontsManager, requestedDrawingMode);
} }
Scene* DrawingContext::getScene() const
{
return mScene.get();
}
DrawingSurface* DrawingContext::getSurface() const DrawingSurface* DrawingContext::getSurface() const
{ {
return mSurface; return mSurface;
@ -40,6 +34,10 @@ FontsManager* DrawingContext::getFontsManager() const
void DrawingContext::paint() void DrawingContext::paint()
{ {
mScene->update(mFontsManager, mDrawingMode == DrawingMode::RASTER ? mSurface->getImage() : nullptr); if (mDrawingMode == DrawingMode::GRAPH)
{
mSurface->getScene()->update(mFontsManager);
}
mPainter->paint(this); mPainter->paint(this);
} }

View file

@ -3,7 +3,6 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
class Scene;
class AbstractPainter; class AbstractPainter;
class DrawingSurface; class DrawingSurface;
class FontsManager; class FontsManager;
@ -21,8 +20,6 @@ public:
static std::unique_ptr<DrawingContext> Create(DrawingSurface* surface, FontsManager* fontsManager, DrawingMode requestedDrawingMode); static std::unique_ptr<DrawingContext> Create(DrawingSurface* surface, FontsManager* fontsManager, DrawingMode requestedDrawingMode);
Scene* getScene() const;
DrawingSurface* getSurface() const; DrawingSurface* getSurface() const;
FontsManager* getFontsManager() const; FontsManager* getFontsManager() const;
@ -33,7 +30,7 @@ private:
DrawingMode mDrawingMode; DrawingMode mDrawingMode;
FontsManager* mFontsManager{nullptr}; FontsManager* mFontsManager{nullptr};
DrawingSurface* mSurface{nullptr}; DrawingSurface* mSurface{nullptr};
std::unique_ptr<Scene> mScene;
std::unique_ptr<AbstractPainter> mPainter; std::unique_ptr<AbstractPainter> mPainter;
}; };

View file

@ -1,6 +1,14 @@
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "Image.h" #include "Image.h"
#include "Scene.h"
#include "RootNode.h"
DrawingSurface::DrawingSurface()
{
}
std::unique_ptr<DrawingSurface> DrawingSurface::Create() std::unique_ptr<DrawingSurface> DrawingSurface::Create()
{ {
@ -23,6 +31,15 @@ unsigned DrawingSurface::getHeight() const
return mHeight; return mHeight;
} }
Scene* DrawingSurface::getScene()
{
if (!mScene)
{
mScene = std::make_unique<Scene>();
}
return mScene.get();
}
Image<unsigned char>* DrawingSurface::getImage() Image<unsigned char>* DrawingSurface::getImage()
{ {
if (!mBackingImage) if (!mBackingImage)

View file

@ -2,13 +2,15 @@
#include <memory> #include <memory>
class Scene;
template<typename T> template<typename T>
class Image; class Image;
class DrawingSurface class DrawingSurface
{ {
public: public:
DrawingSurface() = default; DrawingSurface();
virtual ~DrawingSurface() = default; virtual ~DrawingSurface() = default;
static std::unique_ptr<DrawingSurface> Create(); static std::unique_ptr<DrawingSurface> Create();
@ -21,8 +23,11 @@ public:
Image<unsigned char>* getImage(); Image<unsigned char>* getImage();
Scene* getScene();
protected: protected:
unsigned mWidth = 0; unsigned mWidth = 0;
unsigned mHeight = 0; unsigned mHeight = 0;
std::unique_ptr<Scene> mScene;
std::unique_ptr<Image<unsigned char> > mBackingImage; std::unique_ptr<Image<unsigned char> > mBackingImage;
}; };

View file

@ -2,6 +2,7 @@
#include "DrawingContext.h" #include "DrawingContext.h"
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "SceneModel.h"
#include "TriMesh.h" #include "TriMesh.h"
#include "OpenGlShaderProgram.h" #include "OpenGlShaderProgram.h"
@ -64,12 +65,12 @@ void OpenGlMeshPainter::paint(const std::vector<float>& verts, const std::vector
int vertexColorLocation = glGetUniformLocation(mShaderProgram->getHandle(), "ourColor"); int vertexColorLocation = glGetUniformLocation(mShaderProgram->getHandle(), "ourColor");
glUniform4f(vertexColorLocation, float(color[0]), float(color[1]), float(color[2]), float(color[3])); glUniform4f(vertexColorLocation, float(color[0]), float(color[1]), float(color[2]), float(color[3]));
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); glBindVertexArray(0);
} }
void OpenGlMeshPainter::paint(TriMesh* mesh, DrawingContext* context) void OpenGlMeshPainter::paint(SceneModel* model, DrawingContext* context)
{ {
if (!mShaderProgram) if (!mShaderProgram)
{ {
@ -85,27 +86,29 @@ void OpenGlMeshPainter::paint(TriMesh* mesh, DrawingContext* context)
const auto width = float(surface->getWidth()); const auto width = float(surface->getWidth());
const auto height = float(surface->getHeight()); const auto height = float(surface->getHeight());
auto mesh = dynamic_cast<TriMesh*>(model->getMesh());
auto transform = model->getTransform();
auto vertices = mesh->getVerticesFlat<float>(); auto vertices = mesh->getVerticesFlat<float>();
for (std::size_t idx = 0; idx<vertices.size(); idx++) for (std::size_t idx = 0; idx<vertices.size(); idx++)
{ {
if (idx % 3 == 0) if (idx % 3 == 0)
{ {
vertices[idx] = 2*vertices[idx]/width - 1.0; auto x = vertices[idx]*transform.getScaleX() + transform.getLocation().getX();
vertices[idx] = 2*x/width - 1.0;
} }
else if(idx%3 == 1) else if(idx%3 == 1)
{ {
vertices[idx] = 1.0 - 2*vertices[idx]/height; auto y = vertices[idx]*transform.getScaleY() + transform.getLocation().getY();
vertices[idx] = 1.0 - 2*y/height;
} }
} }
const auto indices = mesh->getFaceNodeIds(); const auto indices = mesh->getFaceNodeIds();
std::vector<float> color(4, 1.0f); auto model_color = model->getColor().getAsVectorDouble();
if (mesh->hasVectorAttribute("Color")) std::vector<float> color = {float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3])};
{
auto mesh_color = mesh->getVectorAttribute("Color");
color = {float(mesh_color[0]), float(mesh_color[1]), float(mesh_color[2]), float(mesh_color[3])};
}
paint(vertices, indices, color); paint(vertices, indices, color);
} }

View file

@ -5,14 +5,14 @@
class DrawingContext; class DrawingContext;
class OpenGlShaderProgram; class OpenGlShaderProgram;
class TriMesh; class SceneModel;
class OpenGlMeshPainter class OpenGlMeshPainter
{ {
public: public:
OpenGlMeshPainter(); OpenGlMeshPainter();
void paint(TriMesh* mesh, DrawingContext* context); void paint(SceneModel* model, DrawingContext* context);
private: private:
void initializeShader(); void initializeShader();

View file

@ -3,6 +3,9 @@
#include "DrawingContext.h" #include "DrawingContext.h"
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "Scene.h" #include "Scene.h"
#include "SceneItem.h"
#include "SceneModel.h"
#include "SceneText.h"
#include "TriMesh.h" #include "TriMesh.h"
@ -51,18 +54,19 @@ void OpenGlPainter::paint(DrawingContext* context)
glClearColor(0.5, 0.5, 1.0, 0.0); glClearColor(0.5, 0.5, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
const auto num_mesh = context->getScene()->getNumMeshes(); for(unsigned idx=0; idx<context->getSurface()->getScene()->getNumItems(); idx++)
for (std::size_t idx=0 ; idx< num_mesh; idx++)
{ {
auto mesh = context->getScene()->getMesh(idx); auto scene_item = context->getSurface()->getScene()->getItem(idx);
mMeshPainter->paint(mesh, context); if (scene_item->getType() == SceneItem::Type::MODEL)
{
mMeshPainter->paint(dynamic_cast<SceneModel*>(scene_item), context);
} }
else
auto text_data = context->getScene()->getTextData();
for (const auto& text_item : context->getScene()->getTextData())
{ {
mTextPainter->paint(text_item, context); mTextPainter->paint(dynamic_cast<SceneText*>(scene_item), context);
break; break;
} }
}
glFlush(); glFlush();
} }

View file

@ -10,6 +10,8 @@
#include "OpenGlShaderProgram.h" #include "OpenGlShaderProgram.h"
#include "TextData.h" #include "TextData.h"
#include "SceneText.h"
#include "File.h" #include "File.h"
#ifdef _WIN32 #ifdef _WIN32
@ -69,7 +71,7 @@ void OpenGlTextPainter::initializeBuffers()
glBindVertexArray(0); glBindVertexArray(0);
} }
void OpenGlTextPainter::paint(const TextData& textData, DrawingContext* context) void OpenGlTextPainter::paint(SceneText* text, DrawingContext* context)
{ {
if (!mShaderProgram) if (!mShaderProgram)
{ {
@ -81,12 +83,15 @@ void OpenGlTextPainter::paint(const TextData& textData, DrawingContext* context)
initializeBuffers(); initializeBuffers();
} }
initializeTextures(textData, context); auto text_data = text->getTextData();
initializeTextures(text_data, context);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(mShaderProgram->getHandle()); glUseProgram(mShaderProgram->getHandle());
glUniform3f(glGetUniformLocation(mShaderProgram->getHandle(), "textColor"), 0.0, 0.0, 0.0); glUniform3f(glGetUniformLocation(mShaderProgram->getHandle(), "textColor"), 0.0, 0.0, 0.0);
const auto width = float(context->getSurface()->getWidth()); const auto width = float(context->getSurface()->getWidth());
@ -97,9 +102,11 @@ void OpenGlTextPainter::paint(const TextData& textData, DrawingContext* context)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindVertexArray(mVertexArray); glBindVertexArray(mVertexArray);
float x = textData.mLocation.GetX(); auto transform = text->getTransform();
const float y = height - textData.mLocation.GetY();
for (auto c : textData.mContent) float x = transform.getLocation().getX();
const float y = height - transform.getLocation().getY();
for (auto c : text_data.mContent)
{ {
auto texture = mFontTextures[c].get(); auto texture = mFontTextures[c].get();

View file

@ -8,13 +8,14 @@ class OpenGlFontTexture;
class OpenGlShaderProgram; class OpenGlShaderProgram;
class TextData; class TextData;
class SceneText;
class OpenGlTextPainter class OpenGlTextPainter
{ {
public: public:
OpenGlTextPainter(); OpenGlTextPainter();
void paint(const TextData& textData, DrawingContext* context); void paint(SceneText* text, DrawingContext* context);
private: private:
void initializeShader(); void initializeShader();

View file

@ -3,5 +3,15 @@
class AbstractMesh class AbstractMesh
{ {
public: public:
enum class MeshType
{
LINE,
TRI,
QUAD
};
virtual ~AbstractMesh() = default; virtual ~AbstractMesh() = default;
virtual MeshType getType() const = 0;
}; };

View file

@ -59,6 +59,11 @@ public:
std::vector<double> getVectorAttribute(const std::string& tag) const; std::vector<double> getVectorAttribute(const std::string& tag) const;
MeshType getType() const
{
return MeshType::TRI;
}
private: private:
std::unordered_map<std::string, std::vector<double> > mVectorAttributes; std::unordered_map<std::string, std::vector<double> > mVectorAttributes;
VecNodes mNodes; VecNodes mNodes;

View file

@ -5,9 +5,10 @@
#include "KeyboardEvent.h" #include "KeyboardEvent.h"
#include "Widget.h" #include "Widget.h"
#include "VisualLayer.h"
#include "Scene.h" #include "Scene.h"
#include "TriMesh.h" #include "TriMesh.h"
#include "RootNode.h"
#include "TransformNode.h"
#include "AbstractPainter.h" #include "AbstractPainter.h"
#include "DrawingContext.h" #include "DrawingContext.h"
@ -119,7 +120,10 @@ void Window::doPaint(mt::Screen* screen)
{ {
mPlatformWindow->beforePaint(screen); mPlatformWindow->beforePaint(screen);
mDrawingContext->getScene()->syncLayers(mWidget->getLayers()); if (mScene && mScene->getRootNode()->getNumChildren() == 0)
{
mScene->getRootNode()->addChild(mWidget->getRootNode());
}
mDrawingContext->paint(); mDrawingContext->paint();

View file

@ -2,7 +2,8 @@
#include "TextNode.h" #include "TextNode.h"
#include "GeometryNode.h" #include "GeometryNode.h"
#include "VisualLayer.h" #include "TransformNode.h"
#include "MouseEvent.h" #include "MouseEvent.h"
#include <iostream> #include <iostream>
@ -32,7 +33,7 @@ void Button::setLabel(const std::string& text)
if (text != mLabel) if (text != mLabel)
{ {
mLabel = text; mLabel = text;
mDirty = true; mContentDirty = true;
} }
} }
@ -53,36 +54,36 @@ void Button::onMyMouseEvent(const MouseEvent* event)
} }
} }
void Button::onPaintEvent(const PaintEvent* event) bool Button::isDirty() const
{ {
if (!needsUpdate()) return Widget::isDirty() || mContentDirty;
{ }
return;
}
mLayers.clear();
if (mDirty) void Button::doPaint(const PaintEvent* event)
{ {
mMyLayers.clear(); updateBackground(event);
if(!mVisible) updateLabel(event);
{ }
return;
}
addBackground(event);
if(!mLabel.empty()) void Button::updateLabel(const PaintEvent* event)
{ {
unsigned fontOffset = unsigned(mLabel.size()) * 4; unsigned fontOffset = unsigned(mLabel.size()) * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset, mLocation.GetY() + mSize.mHeight/2 + 4); auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset, mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create(); if (!mTextNode)
auto node = TextNode::Create(mLabel, middle); {
node->setFillColor(mBackgroundColor); mTextNode = TextNode::Create(mLabel, middle);
textLayer->setTextNode(std::move(node)); mRootNode->addChild(mTextNode.get());
mMyLayers.push_back(std::move(textLayer));
}
mDirty = false;
addMyLayers();
} }
if (mMaterialDirty)
{
mTextNode->setFillColor(mBackgroundColor);
}
if (mContentDirty)
{
mTextNode->setContent(mLabel);
mContentDirty = false;
}
} }

View file

@ -8,6 +8,7 @@
class PaintEvent; class PaintEvent;
class MouseEvent; class MouseEvent;
class TextNode;
class Button : public Widget class Button : public Widget
{ {
@ -25,13 +26,19 @@ public:
protected: protected:
void onMyMouseEvent(const MouseEvent* event) override; void onMyMouseEvent(const MouseEvent* event) override;
void onPaintEvent(const PaintEvent* event) override; bool isDirty() const override;
void doPaint(const PaintEvent* event) override;
void updateLabel(const PaintEvent* event);
private: private:
std::string mLabel; std::string mLabel;
clickFunc mClickFunc; clickFunc mClickFunc;
Color mCachedColor; Color mCachedColor;
Color mClickedColor; Color mClickedColor;
std::unique_ptr<TextNode> mTextNode;
bool mContentDirty{true};
}; };
using ButtonUPtr = std::unique_ptr<Button>; using ButtonUPtr = std::unique_ptr<Button>;

View file

@ -27,7 +27,7 @@ void HorizontalSpacer::addWidgetWithScale(WidgetUPtr widget, double scale)
mScales.push_back(scale); mScales.push_back(scale);
} }
void HorizontalSpacer::addChildLayers(const PaintEvent* event) void HorizontalSpacer::updateChildLocations()
{ {
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0); double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0; double offset = 0;
@ -49,20 +49,6 @@ void HorizontalSpacer::addChildLayers(const PaintEvent* event)
} }
child->setBounds(mSize.mWidth, unsigned(delta)); child->setBounds(mSize.mWidth, unsigned(delta));
child->setLocation(DiscretePoint(mLocation.GetX(), mLocation.GetY() + unsigned(offset))); child->setLocation(DiscretePoint(mLocation.GetX(), mLocation.GetY() + unsigned(offset)));
child->onPaintEvent(event);
auto layers = child->getLayers();
mLayers.insert(mLayers.end(), layers.begin(), layers.end());
offset += delta; offset += delta;
} }
} }
void HorizontalSpacer::onPaintEvent(const PaintEvent* event)
{
if (!needsUpdate())
{
return;
}
mLayers.clear();
addChildLayers(event);
}

View file

@ -5,8 +5,6 @@
class HorizontalSpacer : public Widget class HorizontalSpacer : public Widget
{ {
std::vector<double> mScales;
public: public:
HorizontalSpacer(); HorizontalSpacer();
@ -15,10 +13,9 @@ public:
void addWidget(WidgetUPtr widget) override; void addWidget(WidgetUPtr widget) override;
void addWidgetWithScale(WidgetUPtr widget, double scale); void addWidgetWithScale(WidgetUPtr widget, double scale);
private:
void addChildLayers(const PaintEvent* event) override; void updateChildLocations() override;
std::vector<double> mScales;
void onPaintEvent(const PaintEvent* event) override;
}; };
using HorizontalSpacerUPtr = std::unique_ptr<HorizontalSpacer>; using HorizontalSpacerUPtr = std::unique_ptr<HorizontalSpacer>;

View file

@ -1,8 +1,8 @@
#include "Label.h" #include "Label.h"
#include "TextNode.h" #include "TextNode.h"
#include "TransformNode.h"
#include "GeometryNode.h" #include "GeometryNode.h"
#include "VisualLayer.h"
Label::Label() Label::Label()
: Widget(), : Widget(),
@ -21,36 +21,40 @@ void Label::setLabel(const std::string& text)
if (text != mLabel) if (text != mLabel)
{ {
mLabel = text; mLabel = text;
mDirty = true; mContentDirty = true;
} }
} }
void Label::onPaintEvent(const PaintEvent* event) bool Label::isDirty() const
{ {
if (!needsUpdate()) return Widget::isDirty() || mContentDirty;
{ }
return;
}
mLayers.clear();
if (mDirty) void Label::doPaint(const PaintEvent* event)
{ {
mMyLayers.clear(); updateBackground(event);
if(!mVisible) updateLabel(event);
{ }
return;
}
if(!mLabel.empty()) void Label::updateLabel(const PaintEvent* event)
{ {
unsigned fontOffset = unsigned(mLabel.size()) * 4; unsigned fontOffset = unsigned(mLabel.size()) * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset, mLocation.GetY() + mSize.mHeight/2 + 4); auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset, mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create();
auto textElement = TextNode::Create(mLabel, middle); if (!mTextNode)
textElement->setFillColor(mBackgroundColor); {
textLayer->setTextNode(std::move(textElement)); mTextNode = TextNode::Create(mLabel, middle);
mMyLayers.push_back(std::move(textLayer)); mRootNode->addChild(mTextNode.get());
} }
addMyLayers();
if (mMaterialDirty)
{
mTextNode->setFillColor(mBackgroundColor);
}
if (mContentDirty)
{
mTextNode->setContent(mLabel);
mContentDirty = false;
} }
} }

View file

@ -4,6 +4,8 @@
#include <string> #include <string>
class TextNode;
class Label : public Widget class Label : public Widget
{ {
@ -11,14 +13,21 @@ public:
Label(); Label();
virtual ~Label() = default;
static std::unique_ptr<Label> Create(); static std::unique_ptr<Label> Create();
void setLabel(const std::string& text); void setLabel(const std::string& text);
void onPaintEvent(const PaintEvent* event) override;
private: private:
bool isDirty() const override;
void doPaint(const PaintEvent* event) override;
void updateLabel(const PaintEvent* event);
std::string mLabel; std::string mLabel;
std::unique_ptr<TextNode> mTextNode;
bool mContentDirty{true};
}; };

View file

@ -1,9 +1,9 @@
#include "TextBox.h" #include "TextBox.h"
#include "TextNode.h" #include "TextNode.h"
#include "VisualLayer.h"
#include "GeometryNode.h" #include "GeometryNode.h"
#include "KeyboardEvent.h" #include "KeyboardEvent.h"
#include "TransformNode.h"
#include <sstream> #include <sstream>
@ -24,6 +24,7 @@ std::unique_ptr<TextBox> TextBox::Create()
void TextBox::setContent(const std::string& text) void TextBox::setContent(const std::string& text)
{ {
mContent = text; mContent = text;
mContentDirty = true;
} }
std::string TextBox::getContent() const std::string TextBox::getContent() const
@ -34,6 +35,7 @@ std::string TextBox::getContent() const
void TextBox::appendContent(const std::string& text) void TextBox::appendContent(const std::string& text)
{ {
mContent += text; mContent += text;
mContentDirty = true;
} }
bool TextBox::onMyKeyboardEvent(const KeyboardEvent* event) bool TextBox::onMyKeyboardEvent(const KeyboardEvent* event)
@ -72,6 +74,7 @@ bool TextBox::onMyKeyboardEvent(const KeyboardEvent* event)
return true; return true;
} }
/*
void TextBox::onPaintEvent(const PaintEvent* event) void TextBox::onPaintEvent(const PaintEvent* event)
{ {
mMyLayers.clear(); mMyLayers.clear();
@ -101,3 +104,38 @@ void TextBox::onPaintEvent(const PaintEvent* event)
} }
addMyLayers(); addMyLayers();
} }
*/
bool TextBox::isDirty() const
{
return Widget::isDirty() || mContentDirty;
}
void TextBox::doPaint(const PaintEvent* event)
{
updateBackground(event);
updateLabel(event);
}
void TextBox::updateLabel(const PaintEvent* event)
{
unsigned fontOffset = unsigned(mContent.size()) * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset, mLocation.GetY() + mSize.mHeight/2 + 4);
if (!mTextNode)
{
mTextNode = TextNode::Create(mContent, middle);
mRootNode->addChild(mTextNode.get());
}
if (mMaterialDirty)
{
mTextNode->setFillColor(mBackgroundColor);
}
if (mContentDirty)
{
mTextNode->setContent(mContent);
mContentDirty = false;
}
}

View file

@ -4,6 +4,8 @@
#include <string> #include <string>
class TextNode;
class TextBox : public Widget class TextBox : public Widget
{ {
public: public:
@ -17,12 +19,19 @@ public:
void appendContent(const std::string& text); void appendContent(const std::string& text);
void onPaintEvent(const PaintEvent* event) override; //void onPaintEvent(const PaintEvent* event) override;
bool onMyKeyboardEvent(const KeyboardEvent* event) override; bool onMyKeyboardEvent(const KeyboardEvent* event) override;
private: private:
bool isDirty() const override;
void doPaint(const PaintEvent* event) override;
void updateLabel(const PaintEvent* event);
std::string mContent; std::string mContent;
std::unique_ptr<TextNode> mTextNode;
bool mContentDirty{true};
bool mCaps; bool mCaps;
}; };

View file

@ -26,9 +26,8 @@ void VerticalSpacer::AddWidgetWithScale(WidgetUPtr widget, double scale)
mScales.push_back(scale); mScales.push_back(scale);
} }
void VerticalSpacer::addChildLayers(const PaintEvent* event) void VerticalSpacer::updateChildLocations()
{ {
mLayers.clear();
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0); double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0; double offset = 0;
unsigned delta = mSize.mWidth / unsigned(mChildren.size()); unsigned delta = mSize.mWidth / unsigned(mChildren.size());
@ -39,14 +38,7 @@ void VerticalSpacer::addChildLayers(const PaintEvent* event)
double delta = mSize.mWidth * (scale/scaleSum); double delta = mSize.mWidth * (scale/scaleSum);
child->setBounds(unsigned(delta), mSize.mHeight); child->setBounds(unsigned(delta), mSize.mHeight);
child->setLocation(DiscretePoint(mLocation.GetX() + unsigned(offset), mLocation.GetY())); child->setLocation(DiscretePoint(mLocation.GetX() + unsigned(offset), mLocation.GetY()));
child->onPaintEvent(event);
auto layers = child->getLayers();
mLayers.insert(mLayers.end(), layers.begin(), layers.end());
offset += delta; offset += delta;
} }
} }
void VerticalSpacer::onPaintEvent(const PaintEvent* event)
{
addChildLayers(event);
}

View file

@ -4,7 +4,6 @@
class VerticalSpacer : public Widget class VerticalSpacer : public Widget
{ {
std::vector<double> mScales;
public: public:
VerticalSpacer(); VerticalSpacer();
@ -15,9 +14,9 @@ public:
void AddWidgetWithScale(WidgetUPtr widget, double scale); void AddWidgetWithScale(WidgetUPtr widget, double scale);
void addChildLayers(const PaintEvent* event) override; private:
void updateChildLocations() override;
void onPaintEvent(const PaintEvent* event) override; std::vector<double> mScales;
}; };
using VerticalSpacerUPtr = std::unique_ptr<VerticalSpacer>; using VerticalSpacerUPtr = std::unique_ptr<VerticalSpacer>;

View file

@ -4,9 +4,11 @@
#include "MouseEvent.h" #include "MouseEvent.h"
#include "KeyboardEvent.h" #include "KeyboardEvent.h"
#include "PaintEvent.h" #include "PaintEvent.h"
#include "VisualLayer.h"
#include "AbstractVisualNode.h"
#include "TextNode.h" #include "TextNode.h"
#include "Color.h" #include "TransformNode.h"
#include "RootNode.h"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
@ -17,8 +19,7 @@ Widget::Widget()
mSize({100, 0, 0, 100, 0, 0}), mSize({100, 0, 0, 100, 0, 0}),
mPadding(), mPadding(),
mMargin(), mMargin(),
mMyLayers(), mRootNode(std::make_unique<TransformNode>()),
mLayers(),
mChildren(), mChildren(),
mBorderThickness(0), mBorderThickness(0),
mBackgroundColor(Color(255, 255, 255)), mBackgroundColor(Color(255, 255, 255)),
@ -40,6 +41,7 @@ std::unique_ptr<Widget> Widget::Create()
void Widget::addWidget(WidgetUPtr widget) void Widget::addWidget(WidgetUPtr widget)
{ {
mPendingChildNodes.push_back(widget->getRootNode());
mChildren.push_back(std::move(widget)); mChildren.push_back(std::move(widget));
} }
@ -53,9 +55,9 @@ const DiscretePoint& Widget::getLocation() const
return mLocation; return mLocation;
} }
std::vector<VisualLayer*> Widget::getLayers() const TransformNode* Widget::getRootNode() const
{ {
return mLayers; return mRootNode.get();
} }
void Widget::setSize(const BoundedSize& size) void Widget::setSize(const BoundedSize& size)
@ -63,7 +65,7 @@ void Widget::setSize(const BoundedSize& size)
if (size != mSize) if (size != mSize)
{ {
mSize = size; mSize = size;
mDirty = true; mTransformDirty = true;
} }
} }
@ -77,7 +79,7 @@ void Widget::setMargin(const BoundaryOffset& margin)
if (margin != mMargin) if (margin != mMargin)
{ {
mMargin = margin; mMargin = margin;
mDirty = true; mTransformDirty = true;
} }
} }
@ -91,7 +93,7 @@ void Widget::setPadding(const BoundaryOffset& padding)
if (padding != mPadding) if (padding != mPadding)
{ {
mPadding = padding; mPadding = padding;
mDirty = true; mTransformDirty = true;
} }
} }
@ -99,7 +101,7 @@ void Widget::setBounds(unsigned width, unsigned height)
{ {
if (width != mSize.mWidth || height != mSize.mHeight) if (width != mSize.mWidth || height != mSize.mHeight)
{ {
mDirty = true; mTransformDirty = true;
mSize.mWidth = width; mSize.mWidth = width;
mSize.mHeight = height; mSize.mHeight = height;
} }
@ -110,7 +112,7 @@ void Widget::setBackgroundColor(const Color& color)
if (mBackgroundColor != color) if (mBackgroundColor != color)
{ {
mBackgroundColor = std::move(color); mBackgroundColor = std::move(color);
mDirty = true; mMaterialDirty = true;
} }
} }
@ -119,7 +121,7 @@ void Widget::setLocation(const DiscretePoint& loc)
if (mLocation != loc) if (mLocation != loc)
{ {
mLocation = loc; mLocation = loc;
mDirty = true; mTransformDirty = true;
} }
} }
@ -127,35 +129,19 @@ void Widget::setVisible(bool visible)
{ {
if (mVisible != visible) if (mVisible != visible)
{ {
mDirty = true; mVisibilityDirty = true;
} }
mVisible = visible; mVisible = visible;
} }
void Widget::addMyLayers() bool Widget::isDirty() const
{ {
mLayers.clear(); return mTransformDirty || mMaterialDirty || mVisibilityDirty || mPendingChildNodes.size() > 0;
mLayers.reserve(mMyLayers.size());
auto getRaw = [](const VisualLayerUPtr& uptr){return uptr.get();};
std::transform(mMyLayers.begin(), mMyLayers.end(), std::back_inserter(mLayers), getRaw);
}
void Widget::addChildLayers(const PaintEvent* event)
{
for(auto& child: mChildren)
{
child->setBounds(mSize.mWidth, mSize.mHeight);
child->setLocation(mLocation);
child->onPaintEvent(event);
const auto layers = child->getLayers();
mLayers.insert(mLayers.end(), layers.begin(), layers.end());
}
} }
bool Widget::needsUpdate() const bool Widget::needsUpdate() const
{ {
if (mDirty) if (isDirty())
{ {
return true; return true;
} }
@ -169,26 +155,48 @@ bool Widget::needsUpdate() const
return false; return false;
} }
void Widget::doPaint(const PaintEvent* event)
{
updateBackground(event);
}
void Widget::onPaintEvent(const PaintEvent* event) void Widget::onPaintEvent(const PaintEvent* event)
{ {
if (!needsUpdate()) if (!needsUpdate())
{ {
return; return;
} }
mLayers.clear();
if (mDirty) if (isDirty())
{ {
mMyLayers.clear(); doPaint(event);
if(!mVisible)
mTransformDirty = false;
mMaterialDirty = false;
mVisibilityDirty = false;
}
for (auto node : mPendingChildNodes)
{ {
return; mRootNode->addChild(node);
} }
addBackground(event); mPendingChildNodes.clear();
mDirty = false;
updateChildLocations();
for(auto& child: mChildren)
{
child->onPaintEvent(event);
}
}
void Widget::updateChildLocations()
{
for(auto& child: mChildren)
{
child->setBounds(mSize.mWidth, mSize.mHeight);
child->setLocation(mLocation);
} }
addMyLayers();
addChildLayers(event);
} }
bool Widget::contains(const DiscretePoint& loc) const bool Widget::contains(const DiscretePoint& loc) const
@ -267,16 +275,32 @@ void Widget::onMyMouseEvent(const MouseEvent* event)
} }
void Widget::addBackground(const PaintEvent* event) void Widget::updateBackground(const PaintEvent* event)
{ {
unsigned locX = mLocation.GetX() + mMargin.mLeft; unsigned locX = mLocation.GetX() + mMargin.mLeft;
unsigned locY = mLocation.GetY() + mMargin.mTop; unsigned locY = mLocation.GetY() + mMargin.mTop;
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight; unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom; unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
auto node = RectangleNode::Create(DiscretePoint(locX, locY), deltaX, deltaY); if (!mBackgroundNode)
node->setFillColor(mBackgroundColor); {
auto layer = VisualLayer::Create(); mRootNode->addChild(mBackgroundNode.get());
layer->setShapeNode(std::move(node)); }
mMyLayers.push_back(std::move(layer));
if (mTransformDirty)
{
mBackgroundNode->setWidth(deltaX);
mBackgroundNode->setHeight(deltaY);
mBackgroundNode->setLocation(DiscretePoint(locX, locY));
}
if (mMaterialDirty)
{
mBackgroundNode->setFillColor(mBackgroundColor);
}
if (mVisibilityDirty)
{
mBackgroundNode->setIsVisible(mVisible);
}
} }

View file

@ -10,7 +10,9 @@ class MouseEvent;
class KeyboardEvent; class KeyboardEvent;
class PaintEvent; class PaintEvent;
class VisualLayer; class AbstractVisualNode;
class TransformNode;
class RectangleNode;
class Widget class Widget
{ {
@ -71,7 +73,7 @@ public:
BoundedSize getSize() const; BoundedSize getSize() const;
std::vector<VisualLayer*> getLayers() const; TransformNode* getRootNode() const;
const DiscretePoint& getLocation() const; const DiscretePoint& getLocation() const;
@ -106,27 +108,38 @@ protected:
virtual void onMyMouseEvent(const MouseEvent* event); virtual void onMyMouseEvent(const MouseEvent* event);
virtual void addChildLayers(const PaintEvent* event); virtual void updateBackground(const PaintEvent* event);
virtual void addBackground(const PaintEvent* event); virtual void doPaint(const PaintEvent* event);
virtual void updateChildLocations();
void addMyLayers(); void addMyLayers();
bool needsUpdate() const; bool needsUpdate() const;
protected: protected:
virtual bool isDirty() const;
DiscretePoint mLocation; DiscretePoint mLocation;
BoundedSize mSize; BoundedSize mSize;
BoundaryOffset mPadding; BoundaryOffset mPadding;
BoundaryOffset mMargin; BoundaryOffset mMargin;
std::vector<std::unique_ptr<VisualLayer> > mMyLayers;
std::vector<VisualLayer*> mLayers; std::unique_ptr<TransformNode> mRootNode;
std::vector<std::unique_ptr<Widget> > mChildren; std::vector<std::unique_ptr<Widget> > mChildren;
unsigned mBorderThickness{0}; unsigned mBorderThickness{0};
Color mBackgroundColor; Color mBackgroundColor;
Color mBorderColor; Color mBorderColor;
bool mVisible{false}; bool mVisible{false};
bool mDirty{true};
std::unique_ptr<RectangleNode> mBackgroundNode;
bool mTransformDirty{true};
bool mMaterialDirty{true};
bool mVisibilityDirty{true};
std::vector<TransformNode*> mPendingChildNodes;
}; };
using WidgetUPtr = std::unique_ptr<Widget>; using WidgetUPtr = std::unique_ptr<Widget>;

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "SceneModel.h"
#include "AbstractMesh.h" #include "AbstractMesh.h"
#include "Image.h" #include "Image.h"
#include "DiscretePoint.h" #include "DiscretePoint.h"
@ -19,9 +21,9 @@ public:
virtual ~AbstractVisualNode() = default; virtual ~AbstractVisualNode() = default;
AbstractMesh* getMesh() const SceneItem* getSceneItem() const
{ {
return mMesh.get(); return mSceneItem.get();
} }
virtual void update(FontsManager* fontsManager) virtual void update(FontsManager* fontsManager)
@ -29,34 +31,43 @@ public:
} }
virtual void updateMesh()
{
}
virtual void updateTexture(FontsManager* fontsManager)
{
}
Image<unsigned char>* getImage() const Image<unsigned char>* getImage() const
{ {
return mImage.get(); return mImage.get();
} }
const DiscretePoint& getLocation() const void syncChildren(const std::vector<AbstractVisualNode*>& children)
{ {
return mLocation; mChildren = children;
} }
Image<unsigned char>* getTexture() const void addChild(AbstractVisualNode* child)
{ {
return mTexture.get(); mChildren.push_back(child);
}
const std::vector<AbstractVisualNode*>& getChildren() const
{
return mChildren;
}
void setIsVisible(bool isVisible)
{
mIsVisible = isVisible;
}
unsigned getNumChildren() const
{
return mChildren.size();
} }
protected: protected:
DiscretePoint mLocation; DiscretePoint mLocation;
std::unique_ptr<AbstractMesh> mMesh; std::unique_ptr<SceneItem> mSceneItem;
std::unique_ptr<Image<unsigned char> > mImage; std::unique_ptr<Image<unsigned char> > mImage;
std::unique_ptr<Image<unsigned char> > mTexture;
std::vector<AbstractVisualNode*> mChildren;
bool mIsVisible{true};
bool mTransformIsDirty{true};
}; };

View file

@ -1,9 +1,14 @@
list(APPEND visual_elements_LIB_INCLUDES list(APPEND visual_elements_LIB_INCLUDES
GeometryNode.cpp GeometryNode.cpp
RectangleNode.cpp RectangleNode.cpp
MaterialNode.cpp
TextNode.cpp TextNode.cpp
VisualLayer.cpp
Scene.cpp Scene.cpp
SceneModel.cpp
SceneItem.cpp
SceneText.cpp
Transform.cpp
Texture.cpp
) )
add_library(visual_elements SHARED ${visual_elements_LIB_INCLUDES}) add_library(visual_elements SHARED ${visual_elements_LIB_INCLUDES})

View file

@ -1,41 +1,23 @@
#include "GeometryNode.h" #include "GeometryNode.h"
GeometryNode::GeometryNode(const DiscretePoint& location) GeometryNode::GeometryNode(const DiscretePoint& location)
: AbstractVisualNode(location), : MaterialNode(location),
mFillColor(Color(255, 255, 255)),
mStrokeColor(Color(0, 0, 0)),
mStrokeThickness(1), mStrokeThickness(1),
mType(Type::Path) mType(Type::Path)
{ {
} }
const Color& GeometryNode::getFillColor() const
{
return mFillColor;
}
const Color& GeometryNode::getStrokeColor() const
{
return mStrokeColor;
}
unsigned GeometryNode::getStrokeThickness() const unsigned GeometryNode::getStrokeThickness() const
{ {
return mStrokeThickness; return mStrokeThickness;
} }
void GeometryNode::setFillColor(const Color& color)
{
mFillColor = color;
}
void GeometryNode::setStrokeColor(const Color& color)
{
mStrokeColor = std::move(color);
}
void GeometryNode::setStrokeThickness(unsigned thickness) void GeometryNode::setStrokeThickness(unsigned thickness)
{ {
if (mStrokeThickness != thickness)
{
mGeometryIsDirty = true;
mStrokeThickness = thickness; mStrokeThickness = thickness;
}
} }

View file

@ -1,9 +1,8 @@
#pragma once #pragma once
#include "AbstractVisualNode.h" #include "MaterialNode.h"
#include "Color.h"
class GeometryNode : public AbstractVisualNode class GeometryNode : public MaterialNode
{ {
public: public:
enum class Type enum class Type
@ -18,19 +17,16 @@ public:
GeometryNode(const DiscretePoint& location); GeometryNode(const DiscretePoint& location);
virtual ~GeometryNode() = default; virtual ~GeometryNode() = default;
const Color& getFillColor() const;
const Color& getStrokeColor() const;
unsigned getStrokeThickness() const;
virtual Type getType() = 0; virtual Type getType() = 0;
void setFillColor(const Color& color); unsigned getStrokeThickness() const;
void setStrokeColor(const Color& color);
void setStrokeThickness(unsigned thickness); void setStrokeThickness(unsigned thickness);
private:
Color mFillColor; protected:
Color mStrokeColor;
unsigned mStrokeThickness{0}; unsigned mStrokeThickness{0};
Type mType; Type mType;
bool mGeometryIsDirty{true};
}; };
using GeometryNodePtr = std::unique_ptr<GeometryNode>; using GeometryNodePtr = std::unique_ptr<GeometryNode>;

View file

@ -0,0 +1,37 @@
#include "MaterialNode.h"
MaterialNode::MaterialNode(const DiscretePoint& location)
: AbstractVisualNode(location),
mFillColor(Color(255, 255, 255)),
mStrokeColor(Color(0, 0, 0))
{
}
const Color& MaterialNode::getFillColor() const
{
return mFillColor;
}
const Color& MaterialNode::getStrokeColor() const
{
return mStrokeColor;
}
void MaterialNode::setFillColor(const Color& color)
{
if (mFillColor != color)
{
mMaterialIsDirty = true;
mFillColor = color;
}
}
void MaterialNode::setStrokeColor(const Color& color)
{
if (mStrokeColor != color)
{
mMaterialIsDirty = true;
mStrokeColor = color;
}
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "AbstractVisualNode.h"
#include "Color.h"
class MaterialNode : public AbstractVisualNode
{
public:
MaterialNode(const DiscretePoint& location);
const Color& getFillColor() const;
const Color& getStrokeColor() const;
void setFillColor(const Color& color);
void setStrokeColor(const Color& color);
protected:
Color mFillColor;
Color mStrokeColor;
bool mMaterialIsDirty{true};
};

View file

@ -1,6 +1,7 @@
#include "RectangleNode.h" #include "RectangleNode.h"
#include "Rectangle.h" #include "Rectangle.h"
#include "MeshPrimitives.h" #include "MeshPrimitives.h"
#include <iostream> #include <iostream>
@ -33,18 +34,60 @@ unsigned RectangleNode::getHeight() const
return mHeight; return mHeight;
} }
void RectangleNode::setWidth(unsigned width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mWidth = width;
}
}
void RectangleNode::setHeight(unsigned height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mHeight = height;
}
}
void RectangleNode::setLocation(const DiscretePoint& loc)
{
if (mLocation != loc)
{
mTransformIsDirty = true;
mLocation = loc;
}
}
void RectangleNode::update(FontsManager* fontsManager) void RectangleNode::update(FontsManager* fontsManager)
{ {
updateMesh(); if (!mSceneItem || mGeometryIsDirty)
} {
const auto rect = Rectangle(Point(), 1, 1);
void RectangleNode::updateMesh()
{
const auto rect = Rectangle(mLocation, mWidth, mHeight);
auto mesh = MeshPrimitives::build(rect); auto mesh = MeshPrimitives::build(rect);
auto color = getFillColor();
mesh->addVectorAttribute("Color", color.getAsVectorDouble()); if (!mSceneItem)
mMesh = std::move(mesh); {
mSceneItem = std::make_unique<SceneModel>(std::move(mesh));
}
else
{
dynamic_cast<SceneModel*>(mSceneItem.get())->updateMesh(std::move(mesh));
}
mGeometryIsDirty = false;
}
if (mTransformIsDirty)
{
mSceneItem->updateTransform({mLocation, static_cast<double>(mWidth), static_cast<double>(mHeight)});
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
mSceneItem->updateUniformColor(mFillColor);
mMaterialIsDirty = false;
}
} }

View file

@ -15,10 +15,12 @@ public:
unsigned getWidth() const; unsigned getWidth() const;
unsigned getHeight() const; unsigned getHeight() const;
void update(FontsManager* fontsManager) override; void setWidth(unsigned width);
void setHeight(unsigned height);
void setLocation(const DiscretePoint& loc);
void update(FontsManager* fontsManager) override;
private: private:
void updateMesh() override;
unsigned mWidth{1}; unsigned mWidth{1};
unsigned mHeight{1}; unsigned mHeight{1};
}; };

View file

@ -0,0 +1,14 @@
#pragma once
#include "AbstractVisualNode.h"
class RootNode : public AbstractVisualNode
{
public:
RootNode()
: AbstractVisualNode(DiscretePoint(0, 0))
{
}
};

View file

@ -1,72 +1,42 @@
#include "Scene.h" #include "Scene.h"
#include "VisualLayer.h" #include "RootNode.h"
#include "GeometryNode.h" #include "FontsManager.h"
#include "RectangleNode.h" #include "SceneItem.h"
#include "TextNode.h"
#include "MeshBuilder.h" Scene::Scene()
#include "TriMesh.h" : mRootNode(std::make_unique<RootNode>())
#include "Image.h"
void Scene::syncLayers(const std::vector<VisualLayer*>& layers)
{ {
mLayers = layers;
} }
void Scene::update(FontsManager* fontsManager, Image<unsigned char>* image) void Scene::update(FontsManager* fontsManager)
{ {
if (image) updateNode(mRootNode.get(), fontsManager);
}
void Scene::updateNode(AbstractVisualNode* node, FontsManager* fontsManager)
{
for (auto child : node->getChildren())
{ {
// updateNode(child, fontsManager);
} }
else
{
mWorkingMeshs.clear();
for(auto layer : mLayers)
{
if (layer->hasShapeNode())
{
auto node = layer->getShapeNode();
if (layer->getIsDirty())
{
node->update(fontsManager); node->update(fontsManager);
layer->setIsDirty(false); mSceneItems.push_back(node->getSceneItem());
}
mWorkingMeshs.push_back(dynamic_cast<TriMesh*>(node->getMesh()));
mTextures.push_back(nullptr);
}
else
{
auto node = dynamic_cast<TextNode*>(layer->getTextNode());
if (layer->getIsDirty())
{
node->update(fontsManager);
layer->setIsDirty(false);
}
mTextData.push_back(node->getTextData());
}
}
}
} }
const std::vector<TextData>& Scene::getTextData() const RootNode* Scene::getRootNode() const
{ {
return mTextData; return mRootNode.get();
} }
void Scene::processRectangleNode(RectangleNode* node) unsigned Scene::getNumItems() const
{ {
return mSceneItems.size();
} }
unsigned Scene::getNumMeshes() const SceneItem* Scene::getItem(std::size_t idx) const
{ {
return mWorkingMeshs.size(); return mSceneItems[idx];
}
TriMesh* Scene::getMesh(std::size_t idx) const
{
return mWorkingMeshs[idx];
} }

View file

@ -5,39 +5,25 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
class VisualLayer; class RootNode;
class TriMesh; class AbstractVisualNode;
class SceneItem;
class FontsManager; class FontsManager;
class RectangleNode;
template <typename T>
class Image;
class Scene class Scene
{ {
public: public:
Scene();
Scene() = default; void update(FontsManager* fontsManager);
void syncLayers(const std::vector<VisualLayer*>& layers); unsigned getNumItems() const;
void update(FontsManager* fontsManager, Image<unsigned char>* image = nullptr); SceneItem* getItem(std::size_t idx) const;
unsigned getNumMeshes() const;
TriMesh* getMesh(std::size_t idx) const;
Image<unsigned char>* getTexture(std::size_t idx) const;
const std::vector<TextData>& getTextData() const;
RootNode* getRootNode() const;
private: private:
void processRectangleNode(RectangleNode* node); void updateNode(AbstractVisualNode* node, FontsManager* fontsManager);
std::unique_ptr<RootNode> mRootNode;
std::vector<VisualLayer*> mLayers; std::vector<SceneItem*> mSceneItems;
std::vector<TriMesh*> mWorkingMeshs;
std::vector<Image<unsigned char>* > mTextures;
std::vector<TextData> mTextData;
}; };

View file

@ -0,0 +1,45 @@
#include "SceneItem.h"
SceneItem::SceneItem()
{
}
const Color& SceneItem::getColor() const
{
return mUniformColor;
}
const Transform& SceneItem::getTransform() const
{
return mTransform;
}
bool SceneItem::isVisible() const
{
return mIsVisible;
}
void SceneItem::setIsVisible(bool isVisible)
{
mIsVisible = isVisible;
}
void SceneItem::updateUniformColor(const Color& color)
{
if (mUniformColor != color)
{
mColorIsDirty = true;
mUniformColor = color;
}
}
void SceneItem::updateTransform(const Transform& transform)
{
if (mTransform != transform)
{
mTransformIsDirty = true;
mTransform = transform;
}
}

View file

@ -0,0 +1,41 @@
#pragma once
#include "Color.h"
#include "Transform.h"
class SceneItem
{
public:
enum class Type
{
MODEL,
TEXT
};
SceneItem();
virtual ~SceneItem() = default;
const Color& getColor() const;
const Transform& getTransform() const;
virtual Type getType() const = 0;
bool isVisible() const;
void setIsVisible(bool isVisible);
void updateUniformColor(const Color& color);
void updateTransform(const Transform& transform);
protected:
Transform mTransform;
Color mUniformColor;
bool mColorIsDirty{true};
bool mTransformIsDirty{true};
bool mIsVisible{true};
};

View file

@ -0,0 +1,26 @@
#include "SceneModel.h"
#include "AbstractMesh.h"
SceneModel::SceneModel(std::unique_ptr<AbstractMesh> mesh)
: SceneItem(),
mMesh(std::move(mesh))
{
}
AbstractMesh* SceneModel::getMesh() const
{
return mMesh.get();
}
void SceneModel::updateMesh(std::unique_ptr<AbstractMesh> mesh)
{
mMesh = std::move(mesh);
mMeshIsDirty = true;
}
SceneItem::Type SceneModel::getType() const
{
return SceneItem::Type::MODEL;
}

View file

@ -0,0 +1,31 @@
#pragma once
#include "SceneItem.h"
#include "Texture.h"
#include <vector>
#include <string>
#include <unordered_map>
#include <memory>
class AbstractMesh;
//class Texture;
class SceneModel : public SceneItem
{
public:
SceneModel(std::unique_ptr<AbstractMesh> mesh);
AbstractMesh* getMesh() const;
void updateMesh(std::unique_ptr<AbstractMesh> mesh);
Type getType() const override;
private:
std::unique_ptr<AbstractMesh> mMesh;
std::unique_ptr<Texture> mColorMap;
bool mMeshIsDirty{true};
bool mColorMapIsDirty{true};
};

View file

@ -0,0 +1,25 @@
#include "SceneText.h"
SceneText::SceneText()
{
mTextData.mFont = FontItem("Arial", 16);
}
SceneItem::Type SceneText::getType() const
{
return SceneItem::Type::TEXT;
}
const TextData& SceneText::getTextData() const
{
return mTextData;
}
void SceneText::setContent(const std::string& content)
{
if (mTextData.mContent != content)
{
mTextGeometryIsDirty = true;
mTextData.mContent = content;
}
}

View file

@ -0,0 +1,20 @@
#pragma once
#include "SceneItem.h"
#include "TextData.h"
class SceneText : public SceneItem
{
public:
SceneText();
Type getType() const override;
const TextData& getTextData() const;
void setContent(const std::string& content);
private:
bool mTextGeometryIsDirty{true};
TextData mTextData;
};

View file

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "DiscretePoint.h"
#include "Color.h" #include "Color.h"
#include "FontItem.h" #include "FontItem.h"
@ -8,9 +7,6 @@ class TextData
{ {
public: public:
TextData() = default; TextData() = default;
DiscretePoint mLocation;
std::string mContent; std::string mContent;
Color mFillColor;
Color mStrokeColor;
FontItem mFont; FontItem mFont;
}; };

View file

@ -6,16 +6,14 @@
#include "MeshPrimitives.h" #include "MeshPrimitives.h"
#include "FontItem.h" #include "FontItem.h"
#include "SceneText.h"
#include "Color.h" #include "Color.h"
TextNode::TextNode(const std::string& content, const DiscretePoint& loc) TextNode::TextNode(const std::string& content, const DiscretePoint& loc)
: AbstractVisualNode(loc) : MaterialNode(loc)
{ {
mTextData.mContent = content; mContent= content;
mTextData.mFont = FontItem("Arial", 16);
mTextData.mLocation = loc;
mTextData.mFillColor = Color(255, 255, 255);
mTextData.mStrokeColor = Color(0, 0, 0);
} }
TextNode::~TextNode() TextNode::~TextNode()
@ -28,15 +26,6 @@ std::unique_ptr<TextNode> TextNode::Create(const std::string& content, const Dis
return std::make_unique<TextNode>(content, loc); return std::make_unique<TextNode>(content, loc);
} }
const Color& TextNode::getFillColor() const
{
return mTextData.mFillColor;
}
const Color& TextNode::getStrokeColor() const
{
return mTextData.mStrokeColor;
}
std::string TextNode::getFontLabel() const std::string TextNode::getFontLabel() const
{ {
return {}; return {};
@ -44,41 +33,40 @@ std::string TextNode::getFontLabel() const
std::string TextNode::getContent() const std::string TextNode::getContent() const
{ {
return mTextData.mContent; return mContent;
} }
void TextNode::setContent(const std::string& content) void TextNode::setContent(const std::string& content)
{ {
mTextData.mContent = content; if (mContent != content)
{
mContent = content;
mContentIsDirty = true;
}
} }
void TextNode::setFillColor(const Color& color) void TextNode::update(FontsManager* fontsManager)
{ {
mTextData.mFillColor = color; if (!mSceneItem)
} {
mSceneItem = std::make_unique<SceneText>();
void TextNode::setStrokeColor(const Color& color) }
{
mTextData.mStrokeColor = color; if (!mContentIsDirty)
} {
dynamic_cast<SceneText*>(mSceneItem.get())->setContent(mContent);
void TextNode::update(FontsManager* drawingManager) mContentIsDirty = false;
{ }
updateMesh();
updateTexture(drawingManager); if (mTransformIsDirty)
} {
mSceneItem->updateTransform({mLocation});
const TextData& TextNode::getTextData() const mTransformIsDirty = false;
{ }
return mTextData;
} if (mMaterialIsDirty)
{
void TextNode::updateMesh() mSceneItem->updateUniformColor(mFillColor);
{ mMaterialIsDirty = false;
}
}
void TextNode::updateTexture(FontsManager* fontsManager)
{
} }

View file

@ -1,16 +1,14 @@
#pragma once #pragma once
#include "DiscretePoint.h" #include "MaterialNode.h"
#include "AbstractVisualNode.h"
#include "Color.h"
#include "FontItem.h" #include "FontItem.h"
#include "TextData.h" #include "TextData.h"
#include <memory> #include <memory>
#include <string> #include <string>
class TextNode : public AbstractVisualNode class TextNode : public MaterialNode
{ {
public: public:
TextNode(const std::string& content, const DiscretePoint& loc); TextNode(const std::string& content, const DiscretePoint& loc);
@ -19,25 +17,15 @@ public:
static std::unique_ptr<TextNode> Create(const std::string& content, const DiscretePoint& loc); static std::unique_ptr<TextNode> Create(const std::string& content, const DiscretePoint& loc);
const Color& getFillColor() const;
const Color& getStrokeColor() const;
std::string getContent() const; std::string getContent() const;
std::string getFontLabel() const; std::string getFontLabel() const;
const TextData& getTextData() const;
void setContent(const std::string& content); void setContent(const std::string& content);
void setFillColor(const Color& color);
void setStrokeColor(const Color& color);
void update(FontsManager* fontsManager) override; void update(FontsManager* fontsManager) override;
private: private:
void updateMesh() override; std::string mContent;
void updateTexture(FontsManager* fontsManager) override; bool mContentIsDirty{true};
TextData mTextData;
}; };
using TextNodetr = std::unique_ptr<TextNode>; using TextNodetr = std::unique_ptr<TextNode>;

View file

View file

@ -0,0 +1,7 @@
#pragma once
class Texture
{
public:
Texture() = default;
};

View file

@ -0,0 +1,10 @@
#include "Transform.h"
Transform::Transform(const Point& location, double scaleX, double scaleY, double scaleZ)
: mLocation(location),
mScaleX(scaleX),
mScaleY(scaleY),
mScaleZ(scaleZ)
{
}

View file

@ -0,0 +1,47 @@
#pragma once
#include "Point.h"
class Transform
{
public:
Transform(const Point& location = {}, double scaleX = 1.0, double scaleY = 1.0, double scaleZ = 1.0);
const Point& getLocation() const
{
return mLocation;
}
double getScaleX() const
{
return mScaleX;
}
double getScaleY() const
{
return mScaleY;
}
double getScaleZ() const
{
return mScaleZ;
}
bool operator==(const Transform& rhs) const
{
return (mLocation == rhs.mLocation)
&& (mScaleX == rhs.mScaleX)
&& (mScaleY == rhs.mScaleY)
&& (mScaleZ == rhs.mScaleZ);
}
bool operator!=(const Transform& rhs) const
{
return !operator==(rhs);
}
private:
Point mLocation;
double mScaleX{1};
double mScaleY{1};
double mScaleZ{1};
};

View file

@ -0,0 +1,16 @@
#pragma once
#include "AbstractVisualNode.h"
class TransformNode : public AbstractVisualNode
{
public:
TransformNode()
: AbstractVisualNode(DiscretePoint(0, 0))
{
}
~TransformNode() = default;
};

View file

@ -1,46 +0,0 @@
#include "VisualLayer.h"
#include "GeometryNode.h"
#include "TextNode.h"
VisualLayer::VisualLayer()
: mShape(),
mText()
{
}
std::unique_ptr<VisualLayer> VisualLayer::Create()
{
return std::make_unique<VisualLayer>();
}
bool VisualLayer::hasShapeNode() const
{
return bool(mShape);
}
bool VisualLayer::hasTextNode() const
{
return bool(mText);
}
GeometryNode* VisualLayer::getShapeNode() const
{
return mShape.get();
}
TextNode* VisualLayer::getTextNode() const
{
return mText.get();
}
void VisualLayer::setShapeNode(GeometryNodePtr shape)
{
mShape = std::move(shape);
}
void VisualLayer::setTextNode(std::unique_ptr<TextNode> text)
{
mText = std::move(text);
}

View file

@ -1,37 +0,0 @@
#pragma once
#include <memory>
class GeometryNode;
class TextNode;
class VisualLayer
{
public:
VisualLayer();
static std::unique_ptr<VisualLayer> Create();
GeometryNode* getShapeNode() const;
TextNode* getTextNode() const;
bool hasShapeNode() const;
bool hasTextNode() const;
void setShapeNode(std::unique_ptr<GeometryNode> shape);
void setTextNode(std::unique_ptr<TextNode> text);
bool getIsDirty() const
{
return mIsDirty;
}
void setIsDirty(bool isDirty)
{
mIsDirty = isDirty;
}
private:
bool mIsDirty{true};
std::unique_ptr<GeometryNode> mShape;
std::unique_ptr<TextNode> mText;
};
using VisualLayerUPtr = std::unique_ptr<VisualLayer>;

View file

@ -12,7 +12,6 @@ if(UNIX)
ui_interfaces/x11/XcbWindow.cpp ui_interfaces/x11/XcbWindow.cpp
ui_interfaces/x11/XcbScreen.cpp ui_interfaces/x11/XcbScreen.cpp
ui_interfaces/x11/XcbImage.cpp ui_interfaces/x11/XcbImage.cpp
ui_interfaces/x11/XcbLayerInterface.cpp
ui_interfaces/x11/XcbTextInterface.cpp ui_interfaces/x11/XcbTextInterface.cpp
ui_interfaces/x11/XcbKeyboard.cpp ui_interfaces/x11/XcbKeyboard.cpp
ui_interfaces/x11/XcbGlInterface.cpp ui_interfaces/x11/XcbGlInterface.cpp

View file

@ -12,7 +12,6 @@
#include "XcbScreen.h" #include "XcbScreen.h"
#include "Color.h" #include "Color.h"
#include "UiEvent.h" #include "UiEvent.h"
#include "VisualLayer.h"
#include "XcbKeyboard.h" #include "XcbKeyboard.h"
#include "XcbWindow.h" #include "XcbWindow.h"
#include "XcbEventInterface.h" #include "XcbEventInterface.h"

View file

@ -1,41 +0,0 @@
#include "XcbLayerInterface.h"
#include "XcbTextInterface.h"
#include "RectangleNode.h"
#include "VisualLayer.h"
#include <memory>
void XcbLayerInterface::modifyGcColor(xcb_connection_t* connection, xcb_gcontext_t gc, const Color& color)
{
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
uint32_t values[2] = {color.getAsUInt32(), 0};
xcb_change_gc(connection, gc, mask, values);
}
void XcbLayerInterface::addLayer(xcb_connection_t* connection, xcb_screen_t* screen, xcb_window_t window, xcb_gcontext_t gc, VisualLayer* layer)
{
/*
if(layer->hasText())
{
XcbTextInterface::AddTextElement(connection, screen, window, layer->getText());
}
else if(layer->hasShape())
{
auto shape = layer->getShape();
if(shape->getType() == GeometryNode::Type::Rectangle)
{
const auto rectangle = dynamic_cast<RectangleNode*>(shape);
const auto loc = rectangle->getLocation();
const auto width = static_cast<uint16_t>(rectangle->getWidth());
const auto height = static_cast<uint16_t>(rectangle->getHeight());
xcb_rectangle_t rectangles[] = { { static_cast<int16_t>(loc.GetX()),
static_cast<int16_t>(loc.GetY()), width, height} };
XcbLayerInterface::modifyGcColor(connection, gc, &rectangle->getFillColor());
xcb_poly_fill_rectangle(connection, window, gc, 1, rectangles);
}
}
*/
}

View file

@ -1,15 +0,0 @@
#pragma once
#include <xcb/xcb.h>
class Color;
class VisualLayer;
class XcbLayerInterface
{
public:
static void modifyGcColor(xcb_connection_t* connection, xcb_gcontext_t gc, const Color& color);
static void addLayer(xcb_connection_t* connection, xcb_screen_t* screen, xcb_window_t window, xcb_gcontext_t gc, VisualLayer* layer);
};

View file

@ -1,6 +1,5 @@
#include "XcbTextInterface.h" #include "XcbTextInterface.h"
#include "VisualLayer.h"
#include "Color.h" #include "Color.h"
#include <string.h> #include <string.h>
@ -35,9 +34,8 @@ void XcbTextInterface::AddTextElement(xcb_connection_t* connection,
/* draw the text */ /* draw the text */
const auto content = textElement->getContent(); const auto content = textElement->getContent();
Pixel loc = textElement->getLocation(); //Pixel loc = textElement->getLocation();
xcb_image_text_8(connection, content.length(), window, gc, // xcb_image_text_8(connection, content.length(), window, gc, loc.GetX(), loc.GetY(), content.c_str());
loc.GetX(), loc.GetY(), content.c_str());
/* free the gc */ /* free the gc */
xcb_free_gc(connection, gc); xcb_free_gc(connection, gc);

View file

@ -1,7 +1,6 @@
#include "XcbWindow.h" #include "XcbWindow.h"
#include "Window.h" #include "Window.h"
#include "XcbLayerInterface.h"
#include "XcbScreen.h" #include "XcbScreen.h"
#include "XcbImage.h" #include "XcbImage.h"
#include "Screen.h" #include "Screen.h"