Clean project structure.

This commit is contained in:
jmsgrogan 2023-01-17 10:13:25 +00:00
parent 78a4fa99ff
commit 947bf937fd
496 changed files with 206 additions and 137 deletions

View file

@ -0,0 +1,46 @@
set(MODULE_NAME visual_elements)
list(APPEND visual_elements_LIB_INCLUDES
basic_shapes/RectangleNode.h
basic_shapes/RectangleNode.cpp
basic_shapes/CircleNode.h
basic_shapes/CircleNode.cpp
basic_shapes/LineNode.h
basic_shapes/LineNode.cpp
scene/Scene.h
scene/Scene.cpp
scene/SceneInfo.h
scene/SceneModel.h
scene/SceneModel.cpp
scene/SceneItem.h
scene/SceneItem.cpp
scene/SceneText.h
scene/SceneText.cpp
nodes/MaterialNode.h
nodes/MaterialNode.cpp
nodes/MeshNode.h
nodes/MeshNode.cpp
nodes/TextNode.h
nodes/TextNode.cpp
nodes/GridNode.h
nodes/GridNode.cpp
nodes/GeometryNode.h
nodes/GeometryNode.cpp
nodes/AbstractVisualNode.h
nodes/AbstractVisualNode.cpp
Texture.cpp
)
add_library(${MODULE_NAME} SHARED ${visual_elements_LIB_INCLUDES})
target_include_directories(${MODULE_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/basic_shapes
${CMAKE_CURRENT_SOURCE_DIR}/scene
${CMAKE_CURRENT_SOURCE_DIR}/nodes
)
target_link_libraries(${MODULE_NAME} PUBLIC core geometry fonts mesh image)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src/rendering)
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -0,0 +1,29 @@
#pragma once
#include "Color.h"
#include "FontItem.h"
#include <vector>
class TextData
{
public:
bool operator==(const TextData& rhs) const
{
return (mContent == rhs.mContent)
&& (mLines == rhs.mLines)
&& (mFont == rhs.mFont);
}
bool operator!=(const TextData& rhs) const
{
return !operator==(rhs);
}
public:
TextData() = default;
std::string mContent;
std::vector<std::string> mLines;
FontItem mFont;
};

View file

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

View file

@ -0,0 +1,64 @@
#include "CircleNode.h"
#include "SceneModel.h"
#include "AbstractMesh.h"
#include "MeshPrimitives.h"
#include "SceneInfo.h"
#include "Circle.h"
CircleNode::CircleNode(const Point& location, double radius)
: GeometryNode(location),
mRadius(radius)
{
mMinorRadius = mRadius;
}
CircleNode::Type CircleNode::getType()
{
return Type::Circle;
}
double CircleNode::getRadius() const
{
return mRadius;
}
void CircleNode::setRadius(double radius)
{
if (mRadius != radius)
{
mRadius = radius;
mTransformIsDirty = true;
}
}
void CircleNode::setMinorRadius(double radius)
{
if (mMinorRadius != radius)
{
mMinorRadius = radius;
mTransformIsDirty = true;
}
}
void CircleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
double unit_circle_radius = 0.5;
auto circle = std::make_unique<Circle>(Point{ 0, 0 }, unit_circle_radius);
circle->setMinorRadius(unit_circle_radius*mMinorRadius/mRadius);
mBackgroundItem = std::make_unique<SceneModel>(std::move(circle));
}
else
{
auto mesh = MeshPrimitives::buildCircleAsTriMesh();
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
}
mBackgroundItem->setName(mName + "_Model");
}
void CircleNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation, 2 * mRadius, 2 * mRadius });
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "GeometryNode.h"
class CircleNode : public GeometryNode
{
public:
CircleNode(const Point& location, double radius);
Type getType() override;
double getRadius() const;
void setMinorRadius(double radius);
void setRadius(double radius);
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
void updateTransform() override;
double mRadius{1.0};
double mMinorRadius{ 1.0 };
};

View file

@ -0,0 +1,28 @@
#include "LineNode.h"
LineNode::LineNode(const Point& location, const std::vector<Point>& points)
: GeometryNode(location),
mPoints(points)
{
}
LineNode::Type LineNode::getType()
{
return Type::Line;
}
void LineNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto line = std::make_unique<Line>(Point{ 0, 0 }, mPoints);
mBackgroundItem = std::make_unique<SceneModel>(std::move(line));
}
mBackgroundItem->setName(mName + "_Model");
}
void LineNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation });
}

View file

@ -0,0 +1,23 @@
#pragma once
#include "GeometryNode.h"
#include "SceneInfo.h"
#include "Line.h"
#include <vector>
class LineNode : public GeometryNode
{
public:
LineNode(const Point& location, const std::vector<Point>& points);
Type getType();
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
void updateTransform() override;
std::vector<Point> mPoints;
};

View file

@ -0,0 +1,73 @@
#include "RectangleNode.h"
#include "Rectangle.h"
#include "MeshPrimitives.h"
#include "SceneInfo.h"
RectangleNode::RectangleNode(const Point& loc, double width, double height)
: GeometryNode(loc),
mWidth(width),
mHeight(height)
{
}
std::unique_ptr<RectangleNode> RectangleNode::Create(const Point& loc, double width, double height)
{
return std::make_unique<RectangleNode>(loc, width, height);
}
GeometryNode::Type RectangleNode::getType()
{
return GeometryNode::Type::Rectangle;
}
double RectangleNode::getWidth() const
{
return mWidth;
}
double RectangleNode::getHeight() const
{
return mHeight;
}
void RectangleNode::setWidth(double width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mWidth = width;
}
}
void RectangleNode::setHeight(double height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mHeight = height;
}
}
void RectangleNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
{
if (sceneInfo->mSupportsGeometryPrimitives)
{
auto rect = std::make_unique<ntk::Rectangle>(Point{ 0, 0 }, 1, 1);
mBackgroundItem = std::make_unique<SceneModel>(std::move(rect));
}
else
{
auto mesh = MeshPrimitives::buildRectangleAsTriMesh();
mBackgroundItem = std::make_unique<SceneModel>(std::move(mesh));
}
mBackgroundItem->setName(mName + "_Model");
}
void RectangleNode::updateTransform()
{
mBackgroundItem->updateTransform({ mLocation, mWidth, mHeight });
}

View file

@ -0,0 +1,30 @@
#pragma once
#include "GeometryNode.h"
#include <memory>
class RectangleNode : public GeometryNode
{
public:
RectangleNode(const Point& loc, double width, double height);
static std::unique_ptr<RectangleNode> Create(const Point& loc, double width, double height);
GeometryNode::Type getType() override;
double getWidth() const;
double getHeight() const;
void setWidth(double width);
void setHeight(double height);
private:
void createOrUpdateGeometry(SceneInfo* sceneInfo) override;
void updateTransform() override;
double mWidth{1};
double mHeight{1};
};
using RectangleNodePtr = std::unique_ptr<RectangleNode>;

View file

@ -0,0 +1,77 @@
#include "AbstractVisualNode.h"
AbstractVisualNode::AbstractVisualNode(const Point& location, const std::string& name)
: mLocation(location),
mName(name)
{
}
SceneItem* AbstractVisualNode::getSceneItem(std::size_t idx) const
{
return mSceneItems[idx].get();
}
std::size_t AbstractVisualNode::getNumSceneItems() const
{
return mSceneItems.size();
}
void AbstractVisualNode::update(SceneInfo* sceneInfo)
{
}
Image* AbstractVisualNode::getImage() const
{
return mImage.get();
}
void AbstractVisualNode::syncChildren(const std::vector<AbstractVisualNode*>& children)
{
mChildren = children;
}
void AbstractVisualNode::addChild(AbstractVisualNode* child)
{
mChildren.push_back(child);
}
const std::vector<AbstractVisualNode*>& AbstractVisualNode::getChildren() const
{
return mChildren;
}
void AbstractVisualNode::setIsVisible(bool isVisible)
{
mIsVisible = isVisible;
}
std::size_t AbstractVisualNode::getNumChildren() const
{
return mChildren.size();
}
void AbstractVisualNode::setName(const std::string& name)
{
mName = name;
}
const std::string& AbstractVisualNode::getName() const
{
return mName;
}
bool AbstractVisualNode::getIsVisible() const
{
return mIsVisible;
}
void AbstractVisualNode::setLocation(const Point& loc)
{
if (mLocation != loc)
{
mTransformIsDirty = true;
mLocation = loc;
}
}

View file

@ -0,0 +1,58 @@
#pragma once
#include "SceneModel.h"
#include "AbstractMesh.h"
#include "Image.h"
#include "Point.h"
#include <memory>
#include <iostream>
struct SceneInfo;
class AbstractVisualNode
{
public:
AbstractVisualNode(const Point& location, const std::string& name = {});
virtual ~AbstractVisualNode() = default;
void addChild(AbstractVisualNode* child);
virtual SceneItem* getSceneItem(std::size_t idx) const;
virtual std::size_t getNumSceneItems() const;
std::size_t getNumChildren() const;
const std::vector<AbstractVisualNode*>& getChildren() const;
const std::string& getName() const;
Image* getImage() const;
bool getIsVisible() const;
void syncChildren(const std::vector<AbstractVisualNode*>& children);
void setIsVisible(bool isVisible);
void setName(const std::string& name);
void setLocation(const Point& loc);
virtual void update(SceneInfo* sceneInfo);
protected:
Point mLocation;
std::vector<std::unique_ptr<SceneItem> > mSceneItems;
std::unique_ptr<Image> mImage;
std::vector<AbstractVisualNode*> mChildren;
bool mIsVisible{true};
bool mTransformIsDirty{true};
std::string mName;
};

View file

@ -0,0 +1,89 @@
#include "GeometryNode.h"
#include "SceneInfo.h"
#include "SceneModel.h"
GeometryNode::GeometryNode(const Point& location)
: MaterialNode(location),
mStrokeThickness(1.0),
mType(Type::Path)
{
}
GeometryNode::~GeometryNode()
{
}
SceneItem* GeometryNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mBackgroundItem.get();
}
else
{
return nullptr;
}
}
std::size_t GeometryNode::getNumSceneItems() const
{
return 1;
}
double GeometryNode::getStrokeThickness() const
{
return mStrokeThickness;
}
void GeometryNode::setStrokeThickness(double thickness)
{
if (mStrokeThickness != thickness)
{
mGeometryIsDirty = true;
mStrokeThickness = thickness;
}
}
void GeometryNode::updateMaterial()
{
if (!mBackgroundItem)
{
return;
}
if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor && mStrokeThickness > 0)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
mBackgroundItem->setOutlineThickness(mStrokeThickness);
}
}
void GeometryNode::update(SceneInfo* sceneInfo)
{
if (!mBackgroundItem || mGeometryIsDirty)
{
createOrUpdateGeometry(sceneInfo);
mGeometryIsDirty = false;
}
if (mTransformIsDirty)
{
updateTransform();
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
updateMaterial();
mMaterialIsDirty = false;
}
}

View file

@ -0,0 +1,46 @@
#pragma once
#include "MaterialNode.h"
struct SceneInfo;
class SceneModel;
class GeometryNode : public MaterialNode
{
public:
enum class Type
{
Path,
Rectangle,
Circle,
Arc,
Line
};
public:
GeometryNode(const Point& location);
virtual ~GeometryNode();
virtual Type getType() = 0;
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
double getStrokeThickness() const;
void setStrokeThickness(double thickness);
void update(SceneInfo* sceneInfo) override;
protected:
virtual void createOrUpdateGeometry(SceneInfo* sceneInfo) = 0;
virtual void updateMaterial();
virtual void updateTransform() = 0;
double mStrokeThickness{0};
Type mType;
bool mGeometryIsDirty{true};
std::unique_ptr<SceneModel> mBackgroundItem;
};
using GeometryNodePtr = std::unique_ptr<GeometryNode>;

View file

@ -0,0 +1,140 @@
#include "GridNode.h"
#include "MeshPrimitives.h"
GridNode::GridNode(const Point& location)
: MaterialNode(location)
{
}
void GridNode::setNumX(std::size_t numX)
{
if (mNumberX != numX)
{
mNumberX = numX;
mDataDirty = true;
}
}
void GridNode::setNumY(std::size_t numY)
{
if (mNumberY != numY)
{
mNumberY = numY;
mDataDirty = true;
}
}
void GridNode::setWidth(double width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mWidth = width;
}
}
void GridNode::setHeight(double height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mHeight = height;
}
}
void GridNode::setData(const std::vector<Color>& colors)
{
if (mData != colors)
{
mData = colors;
mDataDirty = true;
}
}
SceneItem* GridNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mBackgroundModel.get();
}
else
{
return mOutlineModel.get();
}
}
std::size_t GridNode::getNumSceneItems() const
{
return 2;
}
void GridNode::update(SceneInfo* sceneInfo)
{
if (!mBackgroundModel || mDataDirty)
{
auto mesh = MeshPrimitives::buildExplodedGridAsTriMesh(mNumberX, mNumberY);
if (!mBackgroundModel)
{
mBackgroundModel = std::make_unique<SceneModel>(std::move(mesh));
mBackgroundModel->setName(mName + "_BackgroundModel");
}
else
{
mBackgroundModel.get()->updateMesh(std::move(mesh));
}
}
if (mOutlineModel || mDataDirty)
{
auto mesh = MeshPrimitives::buildExplodedGridAsLineMesh(mNumberX, mNumberY);
if (!mOutlineModel)
{
mOutlineModel = std::make_unique<SceneModel>(std::move(mesh));
mOutlineModel->setName(mName + "_OulineModel");
}
else
{
mOutlineModel.get()->updateMesh(std::move(mesh));
}
}
if (mDataDirty)
{
auto difference = mNumberX*mNumberY - mData.size();
mData.resize(mNumberX*mNumberY, {});
auto node_data = std::vector<std::vector<double> >(4*mNumberX*mNumberY);
for (unsigned idx=0; idx< node_data.size(); idx++)
{
if (idx < mData.size())
{
node_data[idx] = mData[idx].getAsVectorDouble();
}
}
//mBackgroundModel->getMesh()->addVectorAttribute("Color", mData);
}
if (mTransformIsDirty)
{
auto size = mHeight > mWidth ? mWidth : mHeight;
mBackgroundModel->updateTransform({mLocation, static_cast<double>(size), static_cast<double>(size)});
mOutlineModel->updateTransform({mLocation, static_cast<double>(size), static_cast<double>(size)});
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
mOutlineModel->setFillColor(mStrokeColor);
mMaterialIsDirty = false;
}
mDataDirty = false;
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "MaterialNode.h"
#include "Color.h"
class GridNode : public MaterialNode
{
public:
GridNode(const Point& location);
void setNumX(std::size_t numX);
void setNumY(std::size_t numY);
void setData(const std::vector<Color>& colors);
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
void update(SceneInfo* sceneInfo) override;
void setWidth(double width);
void setHeight(double height);
private:
std::size_t mNumberX{5};
std::size_t mNumberY{5};
double mWidth{1};
double mHeight{1};
bool mDataDirty = true;
std::vector<Color> mData;
std::unique_ptr<SceneModel> mBackgroundModel;
std::unique_ptr<SceneModel> mOutlineModel;
};

View file

@ -0,0 +1,52 @@
#include "MaterialNode.h"
#include <iostream>
MaterialNode::MaterialNode(const Point& 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::setHasStrokeColor(bool hasStroke)
{
if (mHasStrokeColor != hasStroke)
{
mHasStrokeColor = hasStroke;
mMaterialIsDirty = true;
}
}
void MaterialNode::setFillColor(const Color& color)
{
mHasFillColor = true;
if (mFillColor != color)
{
mMaterialIsDirty = true;
mFillColor = color;
}
}
void MaterialNode::setStrokeColor(const Color& color)
{
mHasStrokeColor = true;
if (mStrokeColor != color)
{
mMaterialIsDirty = true;
mStrokeColor = color;
}
}

View file

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

View file

@ -0,0 +1,90 @@
#include "MeshNode.h"
#include <iostream>
MeshNode::MeshNode(const Point& location)
: MaterialNode(location)
{
}
void MeshNode::setWidth(double width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mWidth = width;
}
}
void MeshNode::setHeight(double height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mHeight = height;
}
}
void MeshNode::setMesh(AbstractMesh* mesh)
{
mWorkingMesh = mesh;
mMeshIsDirty = true;
}
SceneItem* MeshNode::getSceneItem(std::size_t idx) const
{
return mModel.get();
}
std::size_t MeshNode::getNumSceneItems() const
{
if (mWorkingMesh)
{
return 1;
}
else
{
return 0;
}
}
void MeshNode::update(SceneInfo* sceneInfo)
{
if (!mModel || mMeshIsDirty)
{
if (!mModel)
{
mModel = std::make_unique<SceneModel>();
mModel->setName(mName + "_MeshModel");
mModel->setShowOutline(true);
}
if (mWorkingMesh)
{
mModel->updateMesh(mWorkingMesh);
mMeshIsDirty = false;
}
}
if (mWorkingMesh && mMeshIsDirty)
{
std::cout << "Updating mesh with " << mWorkingMesh->getNumNodes() << std::endl;
mModel->updateMesh(mWorkingMesh);
mMeshIsDirty = false;
}
if (mTransformIsDirty)
{
auto size = mHeight > mWidth ? mWidth : mHeight;
mModel->updateTransform({mLocation, static_cast<double>(size), static_cast<double>(size)});
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
mModel->setFillColor(mFillColor);
mMaterialIsDirty = false;
}
}

View file

@ -0,0 +1,28 @@
#pragma once
#include "MaterialNode.h"
class AbstractMesh;
class MeshNode : public MaterialNode
{
public:
MeshNode(const Point& location);
void setMesh(AbstractMesh* mesh);
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
void setWidth(double width);
void setHeight(double height);
void update(SceneInfo* sceneInfo) override;
private:
bool mMeshIsDirty{true};
AbstractMesh* mWorkingMesh{nullptr};
double mWidth{1};
double mHeight{1};
std::unique_ptr<SceneModel> mModel;
};

View file

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

View file

@ -0,0 +1,180 @@
#include "TextNode.h"
#include "Rectangle.h"
#include "FontsManager.h"
#include "IFontEngine.h"
#include "MeshPrimitives.h"
#include "FontItem.h"
#include "FontGlyph.h"
#include "SceneInfo.h"
#include "SceneText.h"
#include "Color.h"
#include "StringUtils.h"
#include <iostream>
TextNode::TextNode(const std::string& content, const Point& loc)
: MaterialNode(loc)
{
mTextData.mContent= content;
}
TextNode::~TextNode()
{
}
std::unique_ptr<TextNode> TextNode::Create(const std::string& content, const Point& loc)
{
return std::make_unique<TextNode>(content, loc);
}
std::string TextNode::getFontLabel() const
{
return {};
}
std::string TextNode::getContent() const
{
return mTextData.mContent;
}
double TextNode::getWidth() const
{
return mWidth;
}
double TextNode::getHeight() const
{
return mHeight;
}
void TextNode::setWidth(double width)
{
if (mWidth != width)
{
mTransformIsDirty = true;
mWidth = width;
}
}
void TextNode::setHeight(double height)
{
if (mHeight != height)
{
mTransformIsDirty = true;
mHeight = height;
}
}
void TextNode::setContent(const std::string& content)
{
if (mTextData.mContent != content)
{
mTextData.mContent = content;
mContentIsDirty = true;
}
}
void TextNode::setFont(const FontItem& font)
{
if (mTextData.mFont != font)
{
mTextData.mFont = font;
mContentIsDirty = true;
}
}
SceneItem* TextNode::getSceneItem(std::size_t idx) const
{
if (idx == 0)
{
return mTextItem.get();
}
else
{
return 0;
}
}
std::size_t TextNode::getNumSceneItems() const
{
return 1;
}
void TextNode::updateLines(FontsManager* fontsManager)
{
if (!fontsManager || !fontsManager->usesGlyphs())
{
return;
}
auto original_count = mTextData.mLines.size();
std::vector<std::string> lines = StringUtils::toLines(mTextData.mContent);
std::vector<std::string> output_lines;
for (auto line : lines)
{
double running_width{0};
std::string working_line;
for (auto c : line)
{
auto glyph_advance = fontsManager->getGlyph(mTextData.mFont.getFaceName(), mTextData.mFont.getSize(), c)->getAdvanceX();
if (false)
//if (running_width + glyph_advance > mWidth)
{
output_lines.push_back(working_line);
working_line = c;
running_width = glyph_advance;
}
else
{
working_line += c;
running_width += glyph_advance;
}
}
output_lines.push_back(working_line);
running_width = 0;
}
mTextData.mLines = output_lines;
if (original_count != mTextData.mLines.size())
{
mLinesAreDirty = true;
}
}
void TextNode::update(SceneInfo* sceneInfo)
{
if (!mTextItem)
{
mTextItem = std::make_unique<SceneText>();
mTextItem->setName(mName + "_SceneText");
}
if (mTransformIsDirty || mContentIsDirty)
{
updateLines(sceneInfo->mFontsManager);
}
if (mContentIsDirty || mLinesAreDirty)
{
dynamic_cast<SceneText*>(mTextItem.get())->setTextData(mTextData);
mContentIsDirty = false;
mLinesAreDirty = false;
}
if (mTransformIsDirty)
{
mTextItem->updateTransform({mLocation});
mTransformIsDirty = false;
}
if (mMaterialIsDirty)
{
mTextItem->setFillColor(mFillColor);
mMaterialIsDirty = false;
}
}

View file

@ -0,0 +1,53 @@
#pragma once
#include "MaterialNode.h"
#include "FontItem.h"
#include "TextData.h"
#include <memory>
#include <string>
class FontsManager;
class TextNode : public MaterialNode
{
public:
TextNode(const std::string& content, const Point& loc);
~TextNode();
static std::unique_ptr<TextNode> Create(const std::string& content, const Point& loc);
std::string getContent() const;
std::string getFontLabel() const;
SceneItem* getSceneItem(std::size_t idx) const override;
std::size_t getNumSceneItems() const override;
double getWidth() const;
double getHeight() const;
void setWidth(double width);
void setHeight(double height);
void setContent(const std::string& content);
void setFont(const FontItem& font);
void update(SceneInfo* sceneInfo) override;
private:
void updateLines(FontsManager* fontsManager);
TextData mTextData;
bool mContentIsDirty{true};
bool mLinesAreDirty{true};
double mWidth{1};
double mHeight{1};
std::unique_ptr<SceneItem> mTextItem;
};
using TextNodetr = std::unique_ptr<TextNode>;

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

@ -0,0 +1,92 @@
#include "Scene.h"
#include "RootNode.h"
#include "FontsManager.h"
#include "SceneItem.h"
#include <iostream>
Scene::Scene()
: mRootNode(std::make_unique<RootNode>()),
mSceneInfo(std::make_unique<SceneInfo>()),
mBackGroundColor(Color(255, 255, 255))
{
mRootNode->setName("Scene_RootNode");
}
Scene::~Scene()
{
}
void Scene::update()
{
mSceneItems.clear();
updateNode(mRootNode.get());
}
void Scene::addNode(AbstractVisualNode* node)
{
mRootNode->addChild(node);
}
bool Scene::isEmpty() const
{
return mRootNode->getNumChildren() == 0;
}
const Color& Scene::getBackgroundColor() const
{
return mBackGroundColor;
}
void Scene::setBackgroundColor(const Color& color)
{
mBackGroundColor = color;
}
void Scene::updateNode(AbstractVisualNode* node)
{
node->update(mSceneInfo.get());
for (auto child : node->getChildren())
{
if (child->getIsVisible())
{
updateNode(child);
}
}
for (std::size_t idx=0; idx< node->getNumSceneItems(); idx++)
{
if (auto item = node->getSceneItem(idx))
{
mSceneItems.push_back(item);
}
}
}
const std::vector<SceneItem*>& Scene::getItems() const
{
return mSceneItems;
}
bool Scene::shouldShowMeshOutline() const
{
return mSceneInfo->mShowMeshOutline;
}
void Scene::setShowMeshOutline(bool shouldShow)
{
mSceneInfo->mShowMeshOutline = shouldShow;
}
void Scene::setSupportsGeometryPrimitives(bool supports)
{
mSceneInfo->mSupportsGeometryPrimitives = true;
}
void Scene::setFontsManager(FontsManager* fontsManager)
{
mSceneInfo->mFontsManager = fontsManager;
}

View file

@ -0,0 +1,47 @@
#pragma once
#include "TextData.h"
#include "SceneInfo.h"
#include "Color.h"
#include <vector>
#include <memory>
class RootNode;
class AbstractVisualNode;
class SceneItem;
class Scene
{
public:
Scene();
~Scene();
void addNode(AbstractVisualNode* node);
const std::vector<SceneItem*>& getItems() const;
const Color& getBackgroundColor() const;
bool isEmpty() const;
bool shouldShowMeshOutline() const;
void setBackgroundColor(const Color&);
void setShowMeshOutline(bool shouldShow);
void setFontsManager(FontsManager* fontsManager);
void setSupportsGeometryPrimitives(bool supports);
void update();
private:
void updateNode(AbstractVisualNode* node);
Color mBackGroundColor;
std::unique_ptr<RootNode> mRootNode;
std::vector<SceneItem*> mSceneItems;
std::unique_ptr<SceneInfo> mSceneInfo;
};

View file

@ -0,0 +1,10 @@
#pragma once
#include "FontsManager.h"
struct SceneInfo
{
bool mSupportsGeometryPrimitives{ false };
bool mShowMeshOutline{ false };
FontsManager* mFontsManager{ nullptr };
};

View file

@ -0,0 +1,80 @@
#include "SceneItem.h"
SceneItem::SceneItem()
{
}
const Color& SceneItem::getFillColor() const
{
return mFillColor;
}
const Color& SceneItem::getOutlineColor() const
{
return mOutlineColor;
}
const Transform& SceneItem::getTransform() const
{
return mTransform;
}
double SceneItem::getOutlineThickness() const
{
return mOutlineThickness;
}
bool SceneItem::isVisible() const
{
return mIsVisible;
}
bool SceneItem::hasFillColor() const
{
return mHasFillColor;
}
bool SceneItem::hasOutlineColor() const
{
return mHasOutlineColor;
}
void SceneItem::setIsVisible(bool isVisible)
{
mIsVisible = isVisible;
}
void SceneItem::setOutlineThickness(double thickness)
{
mOutlineThickness = thickness;
}
void SceneItem::setFillColor(const Color& color)
{
if (!mHasFillColor || mFillColor != color)
{
mColorIsDirty = true;
mFillColor = color;
mHasFillColor = true;
}
}
void SceneItem::setOutlineColor(const Color& color)
{
if (!mHasOutlineColor || mOutlineColor != color)
{
mColorIsDirty = true;
mOutlineColor = color;
mHasOutlineColor = true;
}
}
void SceneItem::updateTransform(const Transform& transform)
{
if (mTransform != transform)
{
mTransformIsDirty = true;
mTransform = transform;
}
}

View file

@ -0,0 +1,74 @@
#pragma once
#include "Color.h"
#include "Transform.h"
#include <string>
class SceneItem
{
public:
enum class Type
{
UNSET,
MODEL,
TEXT
};
SceneItem();
virtual ~SceneItem() = default;
const Color& getFillColor() const;
const Color& getOutlineColor() const;
const Transform& getTransform() const;
virtual Type getType() const = 0;
double getOutlineThickness() const;
bool hasFillColor() const;
bool hasOutlineColor() const;
bool isVisible() const;
void setIsVisible(bool isVisible);
void setOutlineColor(const Color& color);
void setOutlineThickness(double thickness);
void setFillColor(const Color& color);
void updateTransform(const Transform& transform);
void setName(const std::string& name)
{
mName = name;
}
const std::string& getName() const
{
return mName;
}
protected:
Transform mTransform;
bool mHasFillColor{ false };
Color mFillColor;
bool mHasOutlineColor{ false };
Color mOutlineColor;
double mOutlineThickness{ 1.0 };
bool mColorIsDirty{true};
bool mTransformIsDirty{true};
bool mIsVisible{true};
std::string mName;
};

View file

@ -0,0 +1,70 @@
#include "SceneModel.h"
#include "AbstractGeometricItem.h"
#include "AbstractMesh.h"
SceneModel::SceneModel(std::unique_ptr<AbstractMesh> mesh)
: SceneItem(),
mMesh(std::move(mesh))
{
}
SceneModel::SceneModel(std::unique_ptr<AbstractGeometricItem> geometry)
: SceneItem(),
mGeometry(std::move(geometry))
{
}
AbstractMesh* SceneModel::getMesh() const
{
if (mMesh)
{
return mMesh.get();
}
else
{
return mRawMesh;
}
}
AbstractGeometricItem* SceneModel::getGeometry() const
{
return mGeometry.get();
}
SceneItem::Type SceneModel::getType() const
{
return SceneItem::Type::MODEL;
}
void SceneModel::setShowOutline(bool showOutline)
{
mShowOutline = showOutline;
}
bool SceneModel::getShowOutline() const
{
return mShowOutline;
}
void SceneModel::updateMesh(std::unique_ptr<AbstractMesh> mesh)
{
mMesh = std::move(mesh);
mGeometryIsDirty = true;
}
void SceneModel::updateGeometry(std::unique_ptr<AbstractGeometricItem> geometry)
{
mGeometry = std::move(geometry);
mGeometryIsDirty = true;
}
void SceneModel::updateMesh(AbstractMesh* mesh)
{
mRawMesh = mesh;
mGeometryIsDirty = true;
}

View file

@ -0,0 +1,42 @@
#pragma once
#include "SceneItem.h"
#include "AbstractGeometricItem.h"
#include "Texture.h"
#include <vector>
#include <string>
#include <unordered_map>
#include <memory>
class AbstractMesh;
class SceneModel : public SceneItem
{
public:
SceneModel() = default;
explicit SceneModel(std::unique_ptr<AbstractMesh> mesh);
explicit SceneModel(std::unique_ptr<AbstractGeometricItem> geometry);
AbstractGeometricItem* getGeometry() const;
AbstractMesh* getMesh() const;
bool getShowOutline() const;
Type getType() const override;
void setShowOutline(bool showOutline);
void updateGeometry(std::unique_ptr<AbstractGeometricItem> geometry);
void updateMesh(std::unique_ptr<AbstractMesh> mesh);
void updateMesh(AbstractMesh* mesh);
private:
AbstractMesh* mRawMesh{nullptr};
std::unique_ptr<AbstractMesh> mMesh;
std::unique_ptr<Texture> mColorMap;
std::unique_ptr<AbstractGeometricItem> mGeometry;
bool mGeometryIsDirty{true};
bool mColorMapIsDirty{true};
bool mShowOutline{false};
};

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::setTextData(const TextData& data)
{
if (mTextData != data)
{
mTextGeometryIsDirty = true;
mTextData = data;
}
}

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 setTextData(const TextData& content);
private:
bool mTextGeometryIsDirty{true};
TextData mTextData;
};