Break out material handling into dedicated class.

This commit is contained in:
jmsgrogan 2023-01-24 09:51:15 +00:00
parent fc44c4c623
commit 73051a5f27
17 changed files with 221 additions and 153 deletions

View file

@ -34,6 +34,7 @@ public:
&& (mScaleY == rhs.mScaleY)
&& (mScaleZ == rhs.mScaleZ);
}
bool operator!=(const Transform& rhs) const
{
return !operator==(rhs);

View file

@ -80,30 +80,32 @@ void DirectX2dPainter::paintRect(SceneModel* model)
const auto max_y = static_cast<float>(loc.getY() + rect->getHeight() * scale_y);
D2D1_RECT_F d2d_rect{ min_x, max_y, max_x, min_y };
const auto material = model->getSolidMaterial();
if (rect->getRadius() == 0.0)
{
if (model->hasFillColor())
if (material.hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
rt->FillRectangle(d2d_rect, mSolidBrush.Get());
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
rt->DrawRectangle(d2d_rect, mSolidBrush.Get(), 1.0f);
}
}
else
{
D2D1_ROUNDED_RECT rounded_rect{ d2d_rect , static_cast<float>(rect->getRadius()), static_cast<float>(rect->getRadius()) };
if (model->hasFillColor())
if (material.hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
rt->FillRoundedRectangle(rounded_rect, mSolidBrush.Get());
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
rt->DrawRoundedRectangle(rounded_rect, mSolidBrush.Get(), 1.0f);
}
}
@ -122,15 +124,16 @@ void DirectX2dPainter::paintCircle(SceneModel* model)
D2D1_POINT_2F d2d_centre{ static_cast<float>(loc.getX()), static_cast<float>(loc.getY()) };
D2D1_ELLIPSE ellipse{ d2d_centre, static_cast<float>(radius), static_cast<float>(radiusy) };
const auto material = model->getSolidMaterial();
auto rt = mD2dInterface->getRenderTarget();
if (model->hasFillColor())
if (material.hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
rt->FillEllipse(ellipse, mSolidBrush.Get());
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
rt->DrawEllipse(ellipse, mSolidBrush.Get(), 1.0f);
}
}
@ -164,14 +167,15 @@ void DirectX2dPainter::paintLine(SceneModel* model)
D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(static_cast<float>(loc.getX()), static_cast<float>(loc.getY()));
rt->SetTransform(translation);
if (model->hasFillColor())
const auto material = model->getSolidMaterial();
if (material.hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
rt->FillGeometry(path_geom.Get(), mSolidBrush.Get());
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
rt->DrawGeometry(path_geom.Get(), mSolidBrush.Get(), 1.0f);
}
@ -231,14 +235,15 @@ void DirectX2dPainter::paintPath(SceneModel* model)
D2D1_MATRIX_3X2_F translation = D2D1::Matrix3x2F::Translation(static_cast<float>(loc.getX()), static_cast<float>(loc.getY()));
rt->SetTransform(translation);
if (model->hasFillColor())
const auto material = model->getSolidMaterial();
if (material.hasFillColor())
{
mSolidBrush->SetColor(toD2dColor(model->getFillColor()));
mSolidBrush->SetColor(toD2dColor(material.getFillColor()));
rt->FillGeometry(path_geom.Get(), mSolidBrush.Get());
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
mSolidBrush->SetColor(toD2dColor(model->getOutlineColor()));
mSolidBrush->SetColor(toD2dColor(material.getStrokeColor()));
rt->DrawGeometry(path_geom.Get(), mSolidBrush.Get(), 1.0f);
}

View file

@ -24,7 +24,7 @@ void DirectXMesh::update(DrawingContext* context, ID3D12Device* device)
const auto width = float(context->getSurface()->getWidth());
const auto height = float(context->getSurface()->getHeight());
auto model_color = mModel->getFillColor().getAsVectorDouble();
auto model_color = mModel->getSolidMaterial().getFillColor().getAsVectorDouble();
std::vector<float> color = { float(model_color[0]), float(model_color[1]), float(model_color[2]), float(model_color[3]) };
auto transform = mModel->getTransform();

View file

@ -45,7 +45,7 @@ void DirectXTextPainter::updateTextFormat(SceneText* text)
mTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
mTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
mTextBrush->SetColor(toD2dColor(text->getFillColor()));
mTextBrush->SetColor(toD2dColor(text->getSolidMaterial().getFillColor()));
}
D2D1::ColorF DirectXTextPainter::toD2dColor(const Color& color)

View file

@ -0,0 +1,78 @@
#include "BasicMaterial.h"
#include "MaterialNode.h"
BasicMaterial::BasicMaterial()
: mFillColor(Color(255, 255, 255)),
mStrokeColor(Color(0, 0, 0))
{
}
BasicMaterial::~BasicMaterial()
{
}
const Color& BasicMaterial::getFillColor() const
{
return mFillColor;
}
const Color& BasicMaterial::getStrokeColor() const
{
return mStrokeColor;
}
double BasicMaterial::getStrokeThickness() const
{
return mStrokeThickness;
}
bool BasicMaterial::hasFillColor() const
{
return mHasFillColor;
}
bool BasicMaterial::hasStrokeColor() const
{
return mHasStrokeColor;
}
bool BasicMaterial::setHasStrokeColor(bool hasStroke)
{
const auto updated = mHasStrokeColor != hasStroke;
mHasStrokeColor = hasStroke;
return updated;
}
bool BasicMaterial::setHasFillColor(bool hasFill)
{
const auto updated = mHasFillColor != hasFill;
mHasFillColor = hasFill;
return updated;
}
bool BasicMaterial::setFillColor(const Color& color)
{
mHasFillColor = true;
const auto updated = mFillColor != color;
mFillColor = color;
return updated;
}
bool BasicMaterial::setStrokeColor(const Color& color)
{
mHasStrokeColor = true;
const auto updated = mStrokeColor != color;
mStrokeColor = color;
return updated;
}
bool BasicMaterial::setStrokeThickness(double thickness)
{
const auto updated = mStrokeThickness != thickness;
mStrokeThickness = thickness;
return updated;
}

View file

@ -0,0 +1,49 @@
#pragma once
#include "Material.h"
#include "Color.h"
class BasicMaterial : public Material
{
public:
BasicMaterial();
virtual ~BasicMaterial();
const Color& getFillColor() const;
const Color& getStrokeColor() const;
double getStrokeThickness() const;
bool hasFillColor() const;
bool hasStrokeColor() const;
bool setHasStrokeColor(bool hasStroke);
bool setHasFillColor(bool hasFill);
bool setFillColor(const Color& color);
bool setStrokeColor(const Color& color);
bool setStrokeThickness(double thickness);
bool operator==(const BasicMaterial& rhs) const
{
return (mHasFillColor == rhs.mHasFillColor)
&& (mHasStrokeColor == rhs.mHasStrokeColor)
&& (mFillColor == rhs.mFillColor)
&& (mStrokeColor == rhs.mStrokeColor)
&& (mStrokeThickness == rhs.mStrokeThickness);
}
bool operator!=(const BasicMaterial& rhs) const
{
return !operator==(rhs);
}
private:
bool mHasFillColor{ false };
bool mHasStrokeColor{ true };
Color mFillColor;
Color mStrokeColor;
double mStrokeThickness{ 1.0 };
};

View file

@ -0,0 +1,12 @@
#pragma once
class Material
{
public:
enum class Type
{
Basic
};
virtual ~Material() = default;
};

View file

@ -55,16 +55,7 @@ void GeometryNode::updateMaterial()
return;
}
if (mHasFillColor)
{
mBackgroundItem->setFillColor(mFillColor);
}
if (mHasStrokeColor && mStrokeThickness > 0)
{
mBackgroundItem->setOutlineColor(mStrokeColor);
mBackgroundItem->setOutlineThickness(mStrokeThickness);
}
mBackgroundItem->updateSolidMaterial(*mMaterial);
}
void GeometryNode::update(SceneInfo* sceneInfo)

View file

@ -137,7 +137,7 @@ void GridNode::update(SceneInfo*)
if (mMaterialIsDirty)
{
mOutlineModel->setFillColor(mStrokeColor);
mOutlineModel->updateSolidMaterial(*mMaterial);
mMaterialIsDirty = false;
}

View file

@ -2,8 +2,7 @@
MaterialNode::MaterialNode(const Transform& transform)
: AbstractVisualNode(transform),
mFillColor(Color(255, 255, 255)),
mStrokeColor(Color(0, 0, 0))
mMaterial(std::make_unique<BasicMaterial>())
{
}
@ -13,52 +12,27 @@ MaterialNode::~MaterialNode()
}
const Color& MaterialNode::getFillColor() const
const BasicMaterial* MaterialNode::getMaterial() const
{
return mFillColor;
}
const Color& MaterialNode::getStrokeColor() const
{
return mStrokeColor;
return mMaterial.get();
}
void MaterialNode::setHasStrokeColor(bool hasStroke)
{
if (mHasStrokeColor != hasStroke)
{
mHasStrokeColor = hasStroke;
mMaterialIsDirty = true;
}
mMaterialIsDirty = mMaterial->setHasStrokeColor(hasStroke);
}
void MaterialNode::setHasFillColor(bool hasFill)
{
if (mHasFillColor != hasFill)
{
mHasFillColor = hasFill;
mMaterialIsDirty = true;
}
mMaterialIsDirty = mMaterial->setHasFillColor(hasFill);
}
void MaterialNode::setFillColor(const Color& color)
{
mHasFillColor = true;
if (mFillColor != color)
{
mMaterialIsDirty = true;
mFillColor = color;
}
mMaterialIsDirty = mMaterial->setFillColor(color);
}
void MaterialNode::setStrokeColor(const Color& color)
{
mHasStrokeColor = true;
if (mStrokeColor != color)
{
mMaterialIsDirty = true;
mStrokeColor = color;
}
mMaterialIsDirty = mMaterial->setStrokeColor(color);
}

View file

@ -1,8 +1,7 @@
#pragma once
#include "AbstractVisualNode.h"
#include "Color.h"
#include "BasicMaterial.h"
class MaterialNode : public AbstractVisualNode
{
@ -10,20 +9,14 @@ public:
MaterialNode(const Transform& transform);
virtual ~MaterialNode();
const Color& getFillColor() const;
const Color& getStrokeColor() const;
const BasicMaterial* getMaterial() const;
void setHasStrokeColor(bool hasStroke);
void setHasFillColor(bool hasFill);
void setFillColor(const Color& color);
void setStrokeColor(const Color& color);
protected:
bool mHasFillColor{ false };
bool mHasStrokeColor{ true };
Color mFillColor;
Color mStrokeColor;
std::unique_ptr<BasicMaterial> mMaterial;
bool mMaterialIsDirty{true};
};

View file

@ -88,7 +88,7 @@ void MeshNode::update(SceneInfo*)
if (mMaterialIsDirty)
{
mModel->setFillColor(mFillColor);
mModel->updateSolidMaterial(*mMaterial);
mMaterialIsDirty = false;
}
}

View file

@ -175,7 +175,7 @@ void TextNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty)
{
mTextItem->setFillColor(mFillColor);
mTextItem->updateSolidMaterial(*mMaterial);
mMaterialIsDirty = false;
}
}

View file

@ -10,14 +10,21 @@ SceneItem::~SceneItem()
}
const Color& SceneItem::getFillColor() const
const Material* SceneItem::getMaterial() const
{
return mFillColor;
if (mMaterial)
{
return mMaterial.get();
}
else
{
return &mSolidMaterial;
}
}
const Color& SceneItem::getOutlineColor() const
const BasicMaterial& SceneItem::getSolidMaterial() const
{
return mOutlineColor;
return mSolidMaterial;
}
const Transform& SceneItem::getTransform() const
@ -30,53 +37,22 @@ const std::string& SceneItem::getName() const
return mName;
}
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)
void SceneItem::updateSolidMaterial(const BasicMaterial& material)
{
mOutlineThickness = thickness;
}
void SceneItem::setFillColor(const Color& color)
if (mSolidMaterial != material)
{
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;
mMaterialIsDirty = true;
mSolidMaterial = material;
}
}

View file

@ -1,6 +1,6 @@
#pragma once
#include "Color.h"
#include "BasicMaterial.h"
#include "Transform.h"
#include <string>
@ -20,47 +20,34 @@ public:
virtual ~SceneItem();
const Color& getFillColor() const;
const Material* getMaterial() const;
const Color& getOutlineColor() const;
const BasicMaterial& getSolidMaterial() const;
const Transform& getTransform() const;
virtual Type getType() const = 0;
double getOutlineThickness() const;
const std::string& getName() 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 setName(const std::string& name);
void updateSolidMaterial(const BasicMaterial& material);
void updateTransform(const Transform& transform);
protected:
Transform mTransform;
bool mHasFillColor{ false };
Color mFillColor;
BasicMaterial mSolidMaterial;
std::unique_ptr<Material> mMaterial;
bool mHasOutlineColor{ false };
Color mOutlineColor;
double mOutlineThickness{ 1.0 };
bool mMaterialIsDirty{true};
bool mColorIsDirty{true};
bool mTransformIsDirty{true};
bool mIsVisible{true};

View file

@ -77,11 +77,11 @@ void SvgNode::update(SceneInfo* sceneInfo)
if (mMaterialIsDirty)
{
if (mHasFillColor)
if (mMaterial->hasFillColor())
{
for (const auto& geom_node : mGeometryNodes)
{
geom_node->setFillColor(mFillColor);
geom_node->setFillColor(mMaterial->getFillColor());
}
}
else
@ -92,11 +92,11 @@ void SvgNode::update(SceneInfo* sceneInfo)
}
}
if (mHasStrokeColor)
if (mMaterial->hasStrokeColor())
{
for (const auto& geom_node : mGeometryNodes)
{
geom_node->setStrokeColor(mStrokeColor);
geom_node->setStrokeColor(mMaterial->getStrokeColor());
}
}
else

View file

@ -74,7 +74,7 @@ void SvgPainter::paintMesh(SvgDocument* document, SceneModel* model, bool showOu
count++;
}
svg_tri->setPoints(points);
svg_tri->setFill(model->getFillColor());
svg_tri->setFill(model->getSolidMaterial().getFillColor());
document->getRoot()->addChild(std::move(svg_tri));
if (showOutline)
@ -92,12 +92,13 @@ void SvgPainter::paintMesh(SvgDocument* document, SceneModel* model, bool showOu
void SvgPainter::setStyle(SceneModel* model, SvgShapeElement* element) const
{
auto transform = model->getTransform();
const auto transform = model->getTransform();
const auto material = model->getSolidMaterial();
if (model->hasFillColor())
if (material.hasFillColor())
{
element->setFill(model->getFillColor());
auto opacity = static_cast<float>(model->getFillColor().getAlpha());
element->setFill(material.getFillColor());
auto opacity = static_cast<float>(material.getFillColor().getAlpha());
if (opacity != 1.0)
{
element->setFillOpacity(opacity);
@ -108,10 +109,10 @@ void SvgPainter::setStyle(SceneModel* model, SvgShapeElement* element) const
element->setNoFill();
}
if (model->hasOutlineColor())
if (material.hasStrokeColor())
{
element->setStrokeColor(model->getOutlineColor());
element->setStrokeWidth(model->getOutlineThickness());
element->setStrokeColor(material.getStrokeColor());
element->setStrokeWidth(material.getStrokeThickness());
}
else
{
@ -195,8 +196,9 @@ void SvgPainter::paintText(SvgDocument* document, SceneText* text) const
svg_text->setLocation(loc);
svg_text->setFontFamily(text->getTextData().mFont.getFaceName());
svg_text->setFill(text->getFillColor());
auto opacity = static_cast<float>(text->getFillColor().getAlpha());
svg_text->setFill(text->getSolidMaterial().getFillColor());
auto opacity = static_cast<float>(text->getSolidMaterial().getFillColor().getAlpha());
if (opacity != 1.0)
{
svg_text->setFillOpacity(opacity);