From 2c7ccb4f6dfb32ab0449742af833a3a8f6035284 Mon Sep 17 00:00:00 2001 From: Haibo Date: Tue, 20 Nov 2018 01:20:06 +0800 Subject: [PATCH] add: geometries supported --- core/base/ActionFiniteTime.cpp | 19 +- core/base/Geometry.cpp | 291 ++++++++++++++++++++++++++ core/base/Geometry.h | 188 +++++++++++++++++ core/base/GeometryNode.cpp | 98 +++++++++ core/base/GeometryNode.h | 92 ++++++++ core/base/Node.cpp | 217 ++++++------------- core/base/Node.h | 198 +++++------------- core/base/Resource.h | 2 +- core/base/Transform.hpp | 17 +- core/base/Transition.cpp | 9 +- core/base/Unit.cpp | 148 +++++++++++++ core/base/Unit.h | 152 ++++++++++++++ core/base/base.hpp | 7 + core/base/d2dres.hpp | 15 +- core/base/render.cpp | 93 +++++--- core/base/render.h | 27 ++- core/easy2d.h | 3 + project/vs2013/Easy2D.vcxproj | 6 + project/vs2013/Easy2D.vcxproj.filters | 18 ++ project/vs2015/Easy2D.vcxproj | 6 + project/vs2015/Easy2D.vcxproj.filters | 18 ++ project/vs2017/Easy2D.vcxproj | 6 + project/vs2017/Easy2D.vcxproj.filters | 18 ++ 23 files changed, 1282 insertions(+), 366 deletions(-) create mode 100644 core/base/Geometry.cpp create mode 100644 core/base/Geometry.h create mode 100644 core/base/GeometryNode.cpp create mode 100644 core/base/GeometryNode.h create mode 100644 core/base/Unit.cpp create mode 100644 core/base/Unit.h diff --git a/core/base/ActionFiniteTime.cpp b/core/base/ActionFiniteTime.cpp index d0ff4bdd..2e9ae017 100644 --- a/core/base/ActionFiniteTime.cpp +++ b/core/base/ActionFiniteTime.cpp @@ -94,14 +94,13 @@ namespace easy2d if (target) { - Point currentPos = target->GetPosition(); - Point diff = currentPos - prev_pos_; + Point diff = target->GetPosition() - prev_pos_; start_pos_ = start_pos_ + diff; - Point newPos = start_pos_ + (delta_pos_ * process_); - target->SetPosition(newPos); + Point new_pos = start_pos_ + (delta_pos_ * process_); + target->SetPosition(new_pos); - prev_pos_ = newPos; + prev_pos_ = new_pos; } } @@ -176,15 +175,13 @@ namespace easy2d float y = height_ * 4 * frac * (1 - frac); y += delta_pos_.y * process_; - Point currentPos = target->GetPosition(); - - Point diff = currentPos - prev_pos_; + Point diff = target->GetPosition() - prev_pos_; start_pos_ = diff + start_pos_; - Point newPos = start_pos_ + Point(x, y); - target->SetPosition(newPos); + Point new_pos = start_pos_ + Point(x, y); + target->SetPosition(new_pos); - prev_pos_ = newPos; + prev_pos_ = new_pos; } } diff --git a/core/base/Geometry.cpp b/core/base/Geometry.cpp new file mode 100644 index 00000000..0390fb48 --- /dev/null +++ b/core/base/Geometry.cpp @@ -0,0 +1,291 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "Geometry.h" +#include "render.h" +#include "logs.h" + +namespace easy2d +{ + //------------------------------------------------------- + // Geometry + //------------------------------------------------------- + + Geometry::Geometry() + { + } + + Geometry::~Geometry() + { + } + + float Geometry::GetLength() + { + float length = 0.f; + if (geo_) + { + // no matter it failed or not + geo_->ComputeLength( + ConvertToD2DMatrix(GetTransformMatrix()), + &length + ); + } + return length; + } + + bool Geometry::ComputePointAt(float length, Point* point, Point* tangent) + { + if (geo_) + { + D2D1_POINT_2F point_tmp, tangent_tmp; + if (SUCCEEDED(geo_->ComputePointAtLength( + length, + ConvertToD2DMatrix(GetTransformMatrix()), + &point_tmp, + &tangent_tmp))) + { + (*point).x = point_tmp.x; + (*point).y = point_tmp.y; + (*tangent).x = tangent_tmp.x; + (*tangent).y = tangent_tmp.y; + return true; + } + } + return false; + } + + bool Geometry::ContainsPoint(Point const & point) + { + if (!geo_) + return false; + + BOOL ret = 0; + // no matter it failed or not + geo_->FillContainsPoint( + point, + ConvertToD2DMatrix(GetTransformMatrix()), + &ret + ); + return !!ret; + } + + GeometryRelation Geometry::GetRelationWith(spGeometry const & other) + { + if (!geo_ || !other->geo_) + return GeometryRelation::Unknown; + + cpTransformedGeometry transformed; + HRESULT hr = devices::Graphics::Instance()->CreateTransformedGeometry( + transformed, + GetTransformMatrix(), + geo_.Get() + ); + + D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN; + + if (SUCCEEDED(hr)) + { + transformed->CompareWithGeometry( + other->geo_.Get(), + ConvertToD2DMatrix(other->GetTransformMatrix()), + &relation + ); + } + return GeometryRelation(relation); + } + + + //------------------------------------------------------- + // RectangleGeometry + //------------------------------------------------------- + + RectangleGeometry::RectangleGeometry() + { + } + + RectangleGeometry::RectangleGeometry(Size const & rect_size) + { + SetSize(rect_size); + } + + RectangleGeometry::~RectangleGeometry() + { + } + + void RectangleGeometry::SetSize(Size const & rect_size) + { + cpRectangleGeometry geo; + if (SUCCEEDED(devices::Graphics::Instance()->CreateRectangleGeometry(geo, Rect(Point{}, rect_size)))) + { + geo_ = geo; + size_ = rect_size; + } + } + + + //------------------------------------------------------- + // CircleGeometry + //------------------------------------------------------- + + CircleGeometry::CircleGeometry() + { + } + + CircleGeometry::CircleGeometry(float radius) + { + SetRadius(radius); + } + + CircleGeometry::~CircleGeometry() + { + } + + void CircleGeometry::SetRadius(float radius) + { + cpEllipseGeometry geo; + if (SUCCEEDED(devices::Graphics::Instance()->CreateEllipseGeometry(geo, Point{}, radius, radius))) + { + geo_ = geo; + radius_ = radius; + } + } + + + //------------------------------------------------------- + // EllipseGeometry + //------------------------------------------------------- + + EllipseGeometry::EllipseGeometry() + { + } + + EllipseGeometry::EllipseGeometry(float radius_x, float radius_y) + { + SetRadius(radius_x, radius_y); + } + + EllipseGeometry::~EllipseGeometry() + { + } + + void EllipseGeometry::SetRadius(float radius_x, float radius_y) + { + cpEllipseGeometry geo; + if (SUCCEEDED(devices::Graphics::Instance()->CreateEllipseGeometry(geo, Point{}, radius_x, radius_y))) + { + geo_ = geo; + radius_x_ = radius_x; + radius_y_ = radius_y; + } + } + + + //------------------------------------------------------- + // PathGeometry + //------------------------------------------------------- + + PathGeometry::PathGeometry() + { + } + + PathGeometry::~PathGeometry() + { + } + + void PathGeometry::BeginPath() + { + current_geometry_ = nullptr; + + ThrowIfFailed( + devices::Graphics::Instance()->CreatePathGeometry(current_geometry_) + ); + + ThrowIfFailed( + current_geometry_->Open(¤t_sink_) + ); + + current_sink_->BeginFigure(D2D1::Point2F(), D2D1_FIGURE_BEGIN_FILLED); + } + + void PathGeometry::EndPath(bool closed) + { + if (current_sink_) + { + current_sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN); + ThrowIfFailed( + current_sink_->Close() + ); + + geo_ = current_geometry_; + + current_sink_ = nullptr; + current_geometry_ = nullptr; + } + } + + void PathGeometry::AddLine(Point const & point) + { + if (current_sink_) + current_sink_->AddLine(point); + } + + void PathGeometry::AddLines(std::vector const& points) + { + if (current_sink_) + { + if (!points.empty()) + { + size_t size = points.size(); + std::vector d2d_points(size); + for (size_t i = 0; i < size; ++i) + { + d2d_points[i] = points[i]; + } + + current_sink_->AddLines( + &d2d_points[0], + static_cast(size) + ); + } + } + } + + void PathGeometry::AddBezier(Point const & point1, Point const & point2, Point const & point3) + { + if (current_sink_) + { + current_sink_->AddBezier( + D2D1::BezierSegment( + point1, + point2, + point3 + ) + ); + } + } + + void PathGeometry::ClearPath() + { + geo_ = nullptr; + current_sink_ = nullptr; + current_geometry_ = nullptr; + } + +} \ No newline at end of file diff --git a/core/base/Geometry.h b/core/base/Geometry.h new file mode 100644 index 00000000..e557e892 --- /dev/null +++ b/core/base/Geometry.h @@ -0,0 +1,188 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include "base.hpp" +#include "Unit.h" + +namespace easy2d +{ + // 几何图形间相交关系 + enum class GeometryRelation : int + { + Unknown, + Disjoin, // 无交集 + IsContained, // 被包含 + Contains, // 包含 + Overlap // 重叠 + }; + + + // 几何抽象 + class Geometry + : public Unit + { + public: + Geometry(); + + virtual ~Geometry(); + + cpGeometry const& GetD2DGeometry() const { return geo_; } + + float GetLength(); + + bool ComputePointAt( + float length, + Point* point, + Point* tangent + ); + + // 判断图形是否包含点 + bool ContainsPoint( + Point const& point + ); + + // 判断两图形相交状态 + GeometryRelation GetRelationWith( + spGeometry const& other + ); + + protected: + cpGeometry geo_; + }; + + + // 几何矩形 + class RectangleGeometry + : public Geometry + { + public: + RectangleGeometry(); + + RectangleGeometry( + Size const& rect_size + ); + + virtual ~RectangleGeometry(); + + Size const& GetSize() const { return size_; } + + void SetSize(Size const& rect_size); + + protected: + Size size_; + }; + + + // 几何圆形 + class CircleGeometry + : public Geometry + { + public: + CircleGeometry(); + + CircleGeometry( + float radius + ); + + virtual ~CircleGeometry(); + + float GetRadius() const { return radius_; } + + void SetRadius( + float radius + ); + + protected: + float radius_; + }; + + + // 几何椭圆 + class EllipseGeometry + : public Geometry + { + public: + EllipseGeometry(); + + EllipseGeometry( + float radius_x, + float radius_y + ); + + virtual ~EllipseGeometry(); + + float GetRadiusX() const { return radius_x_; } + + float GetRadiusY() const { return radius_y_; } + + void SetRadius( + float radius_x, + float radius_y + ); + + protected: + float radius_x_; + float radius_y_; + }; + + + // 几何路径 + class PathGeometry + : public Geometry + { + public: + PathGeometry(); + + virtual ~PathGeometry(); + + // 开始添加路径 + void BeginPath(); + + // 结束路径 + void EndPath( + bool closed = true /* 路径是否闭合 */ + ); + + // 添加一条线段 + void AddLine( + Point const& point /* 端点 */ + ); + + // 添加多条线段 + void AddLines( + std::vector const& points + ); + + // 添加一条三次方贝塞尔曲线 + void AddBezier( + Point const& point1, /* 贝塞尔曲线的第一个控制点 */ + Point const& point2, /* 贝塞尔曲线的第二个控制点 */ + Point const& point3 /* 贝塞尔曲线的终点 */ + ); + + // 清除路径 + void ClearPath(); + + protected: + cpPathGeometry current_geometry_; + cpGeometrySink current_sink_; + }; +} diff --git a/core/base/GeometryNode.cpp b/core/base/GeometryNode.cpp new file mode 100644 index 00000000..d55f4af6 --- /dev/null +++ b/core/base/GeometryNode.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "GeometryNode.h" +#include "render.h" + +namespace easy2d +{ + GeometryNode::GeometryNode() + : fill_color_(Color::White) + , stroke_color_(Color(Color::Black, 0)) + , stroke_width_(1.f) + , outline_join_(StrokeStyle::Miter) + { + } + + GeometryNode::GeometryNode(spGeometry const& geometry) + : GeometryNode() + { + SetGeometry(geometry); + } + + GeometryNode::~GeometryNode() + { + } + + void GeometryNode::SetGeometry(spGeometry const& geometry) + { + geometry_ = geometry; + } + + void GeometryNode::SetFillColor(const Color & color) + { + fill_color_ = color; + } + + void GeometryNode::SetStrokeColor(const Color & color) + { + stroke_color_ = color; + } + + void GeometryNode::SetStrokeWidth(float width) + { + stroke_width_ = std::max(width, 0.f); + } + + void GeometryNode::SetOutlineJoinStyle(StrokeStyle outline_join) + { + outline_join_ = outline_join; + } + + void GeometryNode::OnDraw() + { + if (geometry_) + { + auto graphics = devices::Graphics::Instance(); + graphics->SetTransform(geometry_->GetTransformMatrix() * GetTransformMatrix()); + + graphics->FillGeometry( + geometry_->GetD2DGeometry(), + fill_color_ + ); + + graphics->DrawGeometry( + geometry_->GetD2DGeometry(), + stroke_color_, + stroke_width_, + outline_join_ + ); + } + } + + void GeometryNode::DrawBorder() + { + if (visible_) + { + DrawChildrenBorder(); + } + } + +} diff --git a/core/base/GeometryNode.h b/core/base/GeometryNode.h new file mode 100644 index 00000000..130f5720 --- /dev/null +++ b/core/base/GeometryNode.h @@ -0,0 +1,92 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include "Geometry.h" +#include "Node.h" + +namespace easy2d +{ + // 几何图形 + class GeometryNode + : public Node + { + public: + GeometryNode(); + + GeometryNode( + spGeometry const& geometry + ); + + virtual ~GeometryNode(); + + // 设置形状 + void SetGeometry( + spGeometry const& geometry + ); + + // 设置填充颜色 + void SetFillColor( + const Color& color + ); + + // 设置线条颜色 + void SetStrokeColor( + const Color& color + ); + + // 设置线条宽度 + void SetStrokeWidth( + float width + ); + + // 设置线条相交样式 + void SetOutlineJoinStyle( + StrokeStyle outline_join + ); + + // 获取形状 + spGeometry const& GetGeometry() const { return geometry_; } + + // 获取填充颜色 + Color GetFillColor() const { return fill_color_; } + + // 获取线条颜色 + Color GetStrokeColor() const { return stroke_color_; } + + // 获取线条宽度 + float GetStrokeWidth() const { return stroke_width_; } + + // 获取线条相交样式 + StrokeStyle SetOutlineJoinStyle() const { return outline_join_; } + + virtual void OnDraw() override; + + protected: + virtual void DrawBorder() override; + + protected: + Color fill_color_; + Color stroke_color_; + float stroke_width_; + StrokeStyle outline_join_; + spGeometry geometry_; + }; +} diff --git a/core/base/Node.cpp b/core/base/Node.cpp index 1ff2be8e..541d7660 100644 --- a/core/base/Node.cpp +++ b/core/base/Node.cpp @@ -44,18 +44,16 @@ namespace easy2d , parent_(nullptr) , hash_name_(0) , dirty_sort_(false) - , dirty_transform_(false) , order_(0) - , transform_() , opacity_(1.f) , display_opacity_(1.f) , children_() + , border_color_(Color::Red, 0.6f) , initial_matrix_() , final_matrix_() - , border_color_(Color::Red, 0.6f) + , pivot_(default_pivot_x, default_pivot_y) + , size_() { - transform_.pivot.x = default_pivot_x; - transform_.pivot.y = default_pivot_y; } Node::~Node() @@ -160,13 +158,24 @@ namespace easy2d devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f); } - for (auto child = children_.First(); child; child = child->NextItem()) - { - child->DrawBorder(); - } + DrawChildrenBorder(); } } + void Node::DrawChildrenBorder() + { + for (auto child = children_.First(); child; child = child->NextItem()) + { + child->DrawBorder(); + } + } + + math::Matrix const & Node::GetTransformMatrix() + { + UpdateTransform(); + return final_matrix_; + } + void Node::UpdateTransform() { if (!dirty_transform_) @@ -174,9 +183,14 @@ namespace easy2d dirty_transform_ = false; - final_matrix_ = transform_.ToMatrix(); + Point center{ size_.width * pivot_.x, size_.height * pivot_.y }; + final_matrix_ = math::Matrix::Scaling(transform_.scale, center) + * math::Matrix::Skewing(transform_.skew.x, transform_.skew.y, center) + * math::Matrix::Rotation(transform_.rotation, center) + * math::Matrix::Translation(transform_.position - center); + initial_matrix_ = final_matrix_ * math::Matrix::Translation( - Point{ transform_.size.width * transform_.pivot.x, transform_.size.height * transform_.pivot.y } + Point{ size_.width * pivot_.x, size_.height * pivot_.y } ); if (parent_) @@ -185,10 +199,7 @@ namespace easy2d final_matrix_ = final_matrix_ * parent_->initial_matrix_; } - // 重新构造轮廓 - ThrowIfFailed( - devices::Graphics::Instance()->CreateRectGeometry(border_, final_matrix_, transform_.size) - ); + UpdateBorder(); for (auto child = children_.First(); child; child = child->NextItem()) { @@ -196,6 +207,29 @@ namespace easy2d } } + void Node::UpdateBorder() + { + cpRectangleGeometry rect; + cpTransformedGeometry transformed; + + ThrowIfFailed( + devices::Graphics::Instance()->CreateRectangleGeometry( + rect, + Rect(Point{}, size_) + ) + ); + + ThrowIfFailed( + devices::Graphics::Instance()->CreateTransformedGeometry( + transformed, + final_matrix_, + rect + ) + ); + + border_ = transformed; + } + bool Node::Dispatch(const MouseEvent & e, bool handled) { if (visible_) @@ -258,143 +292,43 @@ namespace easy2d } } - void Node::SetPositionX(float x) - { - this->SetPosition(x, transform_.position.y); - } - - void Node::SetPositionY(float y) - { - this->SetPosition(transform_.position.x, y); - } - - void Node::SetPosition(const Point & p) - { - this->SetPosition(p.x, p.y); - } - - void Node::SetPosition(float x, float y) - { - if (transform_.position.x == x && transform_.position.y == y) - return; - - transform_.position.x = x; - transform_.position.y = y; - dirty_transform_ = true; - } - - void Node::MoveBy(float x, float y) - { - this->SetPosition(transform_.position.x + x, transform_.position.y + y); - } - - void Node::MoveBy(const Point & v) - { - this->MoveBy(v.x, v.y); - } - - void Node::SetScaleX(float scale_x) - { - this->SetScale(scale_x, transform_.scale.y); - } - - void Node::SetScaleY(float scale_y) - { - this->SetScale(transform_.scale.x, scale_y); - } - - void Node::SetScale(float scale) - { - this->SetScale(scale, scale); - } - - void Node::SetScale(float scale_x, float scale_y) - { - if (transform_.scale.x == scale_x && transform_.scale.y == scale_y) - return; - - transform_.scale.x = scale_x; - transform_.scale.y = scale_y; - dirty_transform_ = true; - } - - void Node::SetSkewX(float skew_x) - { - this->SetSkew(skew_x, transform_.skew.y); - } - - void Node::SetSkewY(float skew_y) - { - this->SetSkew(transform_.skew.x, skew_y); - } - - void Node::SetSkew(float skew_x, float skew_y) - { - if (transform_.skew.x == skew_x && transform_.skew.y == skew_y) - return; - - transform_.skew.x = skew_x; - transform_.skew.y = skew_y; - dirty_transform_ = true; - } - - void Node::SetRotation(float angle) - { - if (transform_.rotation == angle) - return; - - transform_.rotation = angle; - dirty_transform_ = true; - } - void Node::SetOpacity(float opacity) { if (opacity_ == opacity) return; display_opacity_ = opacity_ = std::min(std::max(opacity, 0.f), 1.f); - // 更新节点透明度 UpdateOpacity(); } void Node::SetPivotX(float pivot_x) { - this->SetPivot(pivot_x, transform_.pivot.y); + this->SetPivot(pivot_x, pivot_.y); } void Node::SetPivotY(float pivot_y) { - this->SetPivot(transform_.pivot.x, pivot_y); + this->SetPivot(pivot_.x, pivot_y); } void Node::SetPivot(float pivot_x, float pivot_y) { - if (transform_.pivot.x == pivot_x && transform_.pivot.y == pivot_y) + if (pivot_.x == pivot_x && pivot_.y == pivot_y) return; - transform_.pivot.x = pivot_x; - transform_.pivot.y = pivot_y; + pivot_.x = pivot_x; + pivot_.y = pivot_y; dirty_transform_ = true; } void Node::SetWidth(float width) { - this->SetSize(width, transform_.size.height); + this->SetSize(width, size_.height); } void Node::SetHeight(float height) { - this->SetSize(transform_.size.width, height); - } - - void Node::SetSize(float width, float height) - { - if (transform_.size.width == width && transform_.size.height == height) - return; - - transform_.size.width = width; - transform_.size.height = height; - dirty_transform_ = true; + this->SetSize(size_.width, height); } void Node::SetSize(const Size& size) @@ -402,9 +336,14 @@ namespace easy2d this->SetSize(size.width, size.height); } - Transform const& Node::GetTransform() const + void Node::SetSize(float width, float height) { - return transform_; + if (size_.width == width && size_.height == height) + return; + + size_.width = width; + size_.height = height; + dirty_transform_ = true; } void Node::SetTransform(Transform const& transform) @@ -453,7 +392,7 @@ namespace easy2d Rect Node::GetBounds() { - return Rect(Point{}, transform_.size); + return Rect(Point{}, size_); } Node::Nodes Node::GetChildren(String const& name) const @@ -541,7 +480,7 @@ namespace easy2d bool Node::ContainsPoint(const Point& point) { - if (transform_.size.width == 0.f || transform_.size.height == 0.f) + if (size_.width == 0.f || size_.height == 0.f) return false; UpdateTransform(); @@ -549,34 +488,12 @@ namespace easy2d BOOL ret = 0; ThrowIfFailed( border_->FillContainsPoint( - D2D1::Point2F(point.x, point.y), + point, D2D1::Matrix3x2F::Identity(), &ret ) ); - return ret != 0; - } - - bool Node::Intersects(spNode const& node) - { - if (transform_.size.width == 0.f || transform_.size.height == 0.f || node->transform_.size.width == 0.f || node->transform_.size.height == 0.f) - return false; - - // 更新转换矩阵 - UpdateTransform(); - node->UpdateTransform(); - - // 获取相交状态 - D2D1_GEOMETRY_RELATION relation = D2D1_GEOMETRY_RELATION_UNKNOWN; - ThrowIfFailed( - border_->CompareWithGeometry( - node->border_.Get(), - D2D1::Matrix3x2F::Identity(), - &relation - ) - ); - return relation != D2D1_GEOMETRY_RELATION_UNKNOWN && - relation != D2D1_GEOMETRY_RELATION_DISJOINT; + return !!ret; } void Node::SetVisible(bool val) diff --git a/core/base/Node.h b/core/base/Node.h index 4f3284ff..a48a3122 100644 --- a/core/base/Node.h +++ b/core/base/Node.h @@ -21,11 +21,11 @@ #pragma once #include "base.hpp" #include "time.h" +#include "Unit.h" #include "KeyEvent.h" #include "MouseEvent.h" #include "ActionManager.h" #include "TaskManager.h" -#include "Transform.hpp" #include "intrusive/List.hpp" namespace easy2d @@ -34,7 +34,7 @@ namespace easy2d // 节点 class Node - : public ObjectBase + : public Unit , public ActionManager , public TaskManager , protected intrusive::ListItem @@ -58,164 +58,55 @@ namespace easy2d // 更新节点 virtual void OnUpdate(Duration const& dt) {} - // 获取节点显示状态 + // 获取显示状态 bool IsVisible() const { return visible_; } - // 获取节点名称 + // 获取名称 String const& GetName() const { return name_; } - // 获取节点名称的 Hash 值 + // 获取名称的 Hash 值 size_t GetHashName() const { return hash_name_; } - // 获取节点绘图顺序 + // 获取绘图顺序 int GetOrder() const { return order_; } - // 获取节点坐标 - virtual const Point& GetPosition() const { return transform_.position; } + // 获取宽度 + virtual float GetWidth() const { return size_.width * transform_.scale.x; } - // 获取节点宽度 - virtual float GetWidth() const { return transform_.size.width * transform_.scale.x; } + // 获取高度 + virtual float GetHeight() const { return size_.height * transform_.scale.y; } - // 获取节点高度 - virtual float GetHeight() const { return transform_.size.height * transform_.scale.y; } - - // 获取节点大小 + // 获取大小 Size GetSize() const { return Size{ GetWidth(), GetHeight() }; } - // 获取节点的支点 - virtual float GetPivotX() const { return transform_.pivot.x; } + // 获取 x 方向支点 + virtual float GetPivotX() const { return pivot_.x; } - // 获取节点的支点 - virtual float GetPivotY() const { return transform_.pivot.y; } + // 获取 y 方向支点 + virtual float GetPivotY() const { return pivot_.y; } - // 获取节点横向缩放比例 - virtual float GetScaleX() const { return transform_.scale.x; } - - // 获取节点纵向缩放比例 - virtual float GetScaleY() const { return transform_.scale.y; } - - // 获取节点横向错切角度 - virtual float GetSkewX() const { return transform_.skew.x; } - - // 获取节点纵向错切角度 - virtual float GetSkewY() const { return transform_.skew.y; } - - // 获取节点旋转角度 - virtual float GetRotation() const { return transform_.rotation; } - - // 获取节点透明度 + // 获取透明度 virtual float GetOpacity() const { return opacity_; } // 获取包围盒 virtual Rect GetBounds(); + // 获取二维变换矩阵 + virtual math::Matrix const& GetTransformMatrix() override; + // 获取父节点 virtual spNode GetParent() const { return parent_; } - // 设置节点是否显示 + // 设置是否显示 void SetVisible( bool val ); - // 设置节点名称 + // 设置名称 void SetName( String const& name ); - // 设置节点横坐标 - void SetPositionX( - float x - ); - - // 设置节点纵坐标 - void SetPositionY( - float y - ); - - // 设置节点坐标 - void SetPosition( - const Point & point - ); - - // 设置节点坐标 - void SetPosition( - float x, - float y - ); - - // 移动节点 - void MoveBy( - float x, - float y - ); - - // 移动节点 - void MoveBy( - const Point & vector - ); - - // 设置节点绘图顺序 - // 默认为 0 - void SetOrder( - int order - ); - - // 设置横向缩放比例 - // 默认为 1.0 - void SetScaleX( - float scale_x - ); - - // 设置纵向缩放比例 - // 默认为 1.0 - void SetScaleY( - float scale_y - ); - - // 设置缩放比例 - // 默认为 (1.0, 1.0) - void SetScale( - float scale_x, - float scale_y - ); - - // 设置缩放比例 - // 默认为 1.0 - void SetScale( - float scale - ); - - // 设置横向错切角度 - // 默认为 0 - void SetSkewX( - float skew_x - ); - - // 设置纵向错切角度 - // 默认为 0 - void SetSkewY( - float skew_y - ); - - // 设置错切角度 - // 默认为 (0, 0) - void SetSkew( - float skew_x, - float skew_y - ); - - // 设置旋转角度 - // 默认为 0 - void SetRotation( - float rotation - ); - - // 设置透明度 - // 默认为 1.0, 范围 [0, 1] - void SetOpacity( - float opacity - ); - // 设置支点的横向位置 // 默认为 0, 范围 [0, 1] void SetPivotX( @@ -235,36 +126,46 @@ namespace easy2d float pivot_y ); - // 修改节点宽度 + // 修改宽度 void SetWidth( float width ); - // 修改节点高度 + // 修改高度 void SetHeight( float height ); - // 修改节点大小 + // 修改大小 void SetSize( float width, float height ); - // 修改节点大小 + // 修改大小 void SetSize( const Size & size ); - // 设置节点边缘颜色 - void SetBorderColor( - const Color& color + virtual void SetTransform( + Transform const& transform + ) override; + + // 设置透明度 + // 默认为 1.0, 范围 [0, 1] + void SetOpacity( + float opacity ); - Transform const& GetTransform() const; + // 设置绘图顺序 + // 默认为 0 + void SetOrder( + int order + ); - void SetTransform( - Transform const& transform + // 设置边框颜色 + void SetBorderColor( + const Color& color ); // 判断点是否在节点内 @@ -272,11 +173,6 @@ namespace easy2d const Point& point ); - // 判断两物体是否相交 - bool Intersects( - spNode const& node - ); - // 添加子节点 void AddChild( spNode const& child, @@ -340,12 +236,16 @@ namespace easy2d protected: virtual void Update(Duration const& dt); + virtual void DrawBorder(); + + void DrawChildrenBorder(); + + void UpdateBorder(); + void UpdateTransform(); void UpdateOpacity(); - void DrawBorder(); - protected: String name_; size_t hash_name_; @@ -354,12 +254,12 @@ namespace easy2d int order_; bool visible_; bool dirty_sort_; - bool dirty_transform_; Node* parent_; Color border_color_; Children children_; cpGeometry border_; - Transform transform_; + Point pivot_; + Size size_; math::Matrix initial_matrix_; math::Matrix final_matrix_; }; diff --git a/core/base/Resource.h b/core/base/Resource.h index 3a21eef1..862e37b1 100644 --- a/core/base/Resource.h +++ b/core/base/Resource.h @@ -30,7 +30,7 @@ namespace easy2d // ResourceData data; // if (res.Load(&data)) { // LPVOID data = data.buffer; - // DWORD size = data.buffer_size; + // DWORD size_ = data.buffer_size; // } // struct ResourceData diff --git a/core/base/Transform.hpp b/core/base/Transform.hpp index 8554d6f3..c4663ca2 100644 --- a/core/base/Transform.hpp +++ b/core/base/Transform.hpp @@ -29,40 +29,25 @@ namespace easy2d class Transform { public: - Size size; // 大小 float rotation; // 旋转 Point position; // 坐标 Point scale; // 缩放 Point skew; // 错切角度 - Point pivot; // 支点 public: Transform() : position() - , size() , rotation(0) , scale(1.f, 1.f) , skew(0.f, 0.f) - , pivot(0.f, 0.f) {} - inline math::Matrix ToMatrix() const - { - math::Vector2 center{ size.width * pivot.x, size.height * pivot.y }; - return math::Matrix::Scaling(scale.x, scale.y, center) - * math::Matrix::Skewing(skew.x, skew.y, center) - * math::Matrix::Rotation(rotation, center) - * math::Matrix::Translation(position.x - center.x, position.y - center.y); - } - bool operator== (const Transform& other) const { return position == other.position && - size == other.size && scale == other.scale && skew == other.skew && - rotation == other.rotation && - pivot == other.pivot; + rotation == other.rotation; } }; diff --git a/core/base/Transition.cpp b/core/base/Transition.cpp index f9915c17..874a15a1 100644 --- a/core/base/Transition.cpp +++ b/core/base/Transition.cpp @@ -106,7 +106,7 @@ namespace easy2d if (out_scene_) { graphics->PushClip( - out_scene_->GetTransform().ToMatrix(), + out_scene_->GetTransformMatrix(), window_size_ ); graphics->PushLayer(out_layer_, out_layer_prop_); @@ -120,7 +120,7 @@ namespace easy2d if (in_scene_) { graphics->PushClip( - in_scene_->GetTransform().ToMatrix(), + in_scene_->GetTransformMatrix(), window_size_ ); graphics->PushLayer(in_layer_, in_layer_prop_); @@ -332,17 +332,18 @@ namespace easy2d Transition::Init(prev, next); auto transform = Transform{}; - transform.pivot = Point{ 0.5f, 0.5f }; transform.position = Point{ window_size_.width / 2, window_size_.height / 2 }; if (out_scene_) { out_scene_->SetTransform(transform); + out_scene_->SetPivot(0.5f, 0.5f); } if (in_scene_) { in_scene_->SetTransform(transform); + in_scene_->SetPivot(0.5f, 0.5f); } in_layer_prop_.opacity = 0; @@ -383,11 +384,13 @@ namespace easy2d if (out_scene_) { out_scene_->SetTransform(Transform{}); + out_scene_->SetPivot(0.f, 0.f); } if (in_scene_) { in_scene_->SetTransform(Transform{}); + in_scene_->SetPivot(0.f, 0.f); } } } diff --git a/core/base/Unit.cpp b/core/base/Unit.cpp new file mode 100644 index 00000000..6278c6eb --- /dev/null +++ b/core/base/Unit.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "Unit.h" + +namespace easy2d +{ + Unit::Unit() + : transform_() + , dirty_transform_(false) + { + } + + Unit::~Unit() + { + } + + math::Matrix const & Unit::GetTransformMatrix() + { + if (dirty_transform_) + { + UpdateMatrix(); + dirty_transform_ = false; + } + return matrix_cached_; + } + + void Unit::SetPositionX(float x) + { + this->SetPosition(x, transform_.position.y); + } + + void Unit::SetPositionY(float y) + { + this->SetPosition(transform_.position.x, y); + } + + void Unit::SetPosition(const Point & p) + { + this->SetPosition(p.x, p.y); + } + + void Unit::SetPosition(float x, float y) + { + if (transform_.position.x == x && transform_.position.y == y) + return; + + transform_.position.x = x; + transform_.position.y = y; + dirty_transform_ = true; + } + + void Unit::MoveBy(float x, float y) + { + this->SetPosition(transform_.position.x + x, transform_.position.y + y); + } + + void Unit::MoveBy(const Point & v) + { + this->MoveBy(v.x, v.y); + } + + void Unit::SetScaleX(float scale_x) + { + this->SetScale(scale_x, transform_.scale.y); + } + + void Unit::SetScaleY(float scale_y) + { + this->SetScale(transform_.scale.x, scale_y); + } + + void Unit::SetScale(float scale) + { + this->SetScale(scale, scale); + } + + void Unit::SetScale(float scale_x, float scale_y) + { + if (transform_.scale.x == scale_x && transform_.scale.y == scale_y) + return; + + transform_.scale.x = scale_x; + transform_.scale.y = scale_y; + dirty_transform_ = true; + } + + void Unit::SetSkewX(float skew_x) + { + this->SetSkew(skew_x, transform_.skew.y); + } + + void Unit::SetSkewY(float skew_y) + { + this->SetSkew(transform_.skew.x, skew_y); + } + + void Unit::SetSkew(float skew_x, float skew_y) + { + if (transform_.skew.x == skew_x && transform_.skew.y == skew_y) + return; + + transform_.skew.x = skew_x; + transform_.skew.y = skew_y; + dirty_transform_ = true; + } + + void Unit::SetRotation(float angle) + { + if (transform_.rotation == angle) + return; + + transform_.rotation = angle; + dirty_transform_ = true; + } + + void Unit::SetTransform(Transform const& transform) + { + transform_ = transform; + } + + void Unit::UpdateMatrix() + { + Point center; + matrix_cached_ = math::Matrix::Scaling(transform_.scale, center) + * math::Matrix::Skewing(transform_.skew.x, transform_.skew.y, center) + * math::Matrix::Rotation(transform_.rotation, center) + * math::Matrix::Translation(transform_.position - center); + } + +} diff --git a/core/base/Unit.h b/core/base/Unit.h new file mode 100644 index 00000000..76207615 --- /dev/null +++ b/core/base/Unit.h @@ -0,0 +1,152 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include "base.hpp" +#include "Transform.hpp" + +namespace easy2d +{ + class Unit + : public ObjectBase + { + public: + Unit(); + + virtual ~Unit(); + + // 获取坐标 + virtual const Point& GetPosition() const { return transform_.position; } + + // 获取横向缩放比例 + virtual float GetScaleX() const { return transform_.scale.x; } + + // 获取纵向缩放比例 + virtual float GetScaleY() const { return transform_.scale.y; } + + // 获取横向错切角度 + virtual float GetSkewX() const { return transform_.skew.x; } + + // 获取纵向错切角度 + virtual float GetSkewY() const { return transform_.skew.y; } + + // 获取旋转角度 + virtual float GetRotation() const { return transform_.rotation; } + + Transform const& GetTransform() const { return transform_; } + + // 设置横坐标 + void SetPositionX( + float x + ); + + // 设置纵坐标 + void SetPositionY( + float y + ); + + // 设置坐标 + void SetPosition( + const Point & point + ); + + // 设置坐标 + virtual void SetPosition( + float x, + float y + ); + + // 移动 + void MoveBy( + float x, + float y + ); + + // 移动 + void MoveBy( + const Point & vector + ); + + // 设置横向缩放比例 + // 默认为 1.0 + void SetScaleX( + float scale_x + ); + + // 设置纵向缩放比例 + // 默认为 1.0 + void SetScaleY( + float scale_y + ); + + // 设置缩放比例 + // 默认为 (1.0, 1.0) + virtual void SetScale( + float scale_x, + float scale_y + ); + + // 设置缩放比例 + // 默认为 1.0 + void SetScale( + float scale + ); + + // 设置横向错切角度 + // 默认为 0 + void SetSkewX( + float skew_x + ); + + // 设置纵向错切角度 + // 默认为 0 + void SetSkewY( + float skew_y + ); + + // 设置错切角度 + // 默认为 (0, 0) + virtual void SetSkew( + float skew_x, + float skew_y + ); + + // 设置旋转角度 + // 默认为 0 + virtual void SetRotation( + float rotation + ); + + virtual void SetTransform( + Transform const& transform + ); + + // 获取二维变换矩阵 + virtual math::Matrix const& GetTransformMatrix(); + + protected: + virtual void UpdateMatrix(); + + protected: + bool dirty_transform_; + Transform transform_; + math::Matrix matrix_cached_; + }; +} diff --git a/core/base/base.hpp b/core/base/base.hpp index 6db1a397..bfac55ee 100644 --- a/core/base/base.hpp +++ b/core/base/base.hpp @@ -43,12 +43,19 @@ namespace easy2d E2D_DECLARE_SMART_PTR(Image); E2D_DECLARE_SMART_PTR(Music); E2D_DECLARE_SMART_PTR(Task); + + E2D_DECLARE_SMART_PTR(Geometry); + E2D_DECLARE_SMART_PTR(RectangleGeometry); + E2D_DECLARE_SMART_PTR(CircleGeometry); + E2D_DECLARE_SMART_PTR(EllipseGeometry); + E2D_DECLARE_SMART_PTR(PathGeometry); E2D_DECLARE_SMART_PTR(Node); E2D_DECLARE_SMART_PTR(Scene); E2D_DECLARE_SMART_PTR(Sprite); E2D_DECLARE_SMART_PTR(Text); E2D_DECLARE_SMART_PTR(Canvas); + E2D_DECLARE_SMART_PTR(GeometryNode); E2D_DECLARE_SMART_PTR(Action); E2D_DECLARE_SMART_PTR(MoveBy); diff --git a/core/base/d2dres.hpp b/core/base/d2dres.hpp index 4dcb327d..f4462d8c 100644 --- a/core/base/d2dres.hpp +++ b/core/base/d2dres.hpp @@ -41,11 +41,16 @@ namespace easy2d E2D_DECLARE_D2D_SMART_PTR(ID2D1BitmapRenderTarget, cpBitmapRenderTarget); E2D_DECLARE_D2D_SMART_PTR(ID2D1StrokeStyle, cpStrokeStyle); + E2D_DECLARE_D2D_SMART_PTR(ID2D1Geometry, cpGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1RectangleGeometry, cpRectangleGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1EllipseGeometry, cpEllipseGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometryGroup, cpGeometryGroup); + E2D_DECLARE_D2D_SMART_PTR(ID2D1PathGeometry, cpPathGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1TransformedGeometry, cpTransformedGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometrySink, cpGeometrySink); + E2D_DECLARE_D2D_SMART_PTR(ID2D1Layer, cpLayer); E2D_DECLARE_D2D_SMART_PTR(ID2D1Bitmap, cpBitmap); - E2D_DECLARE_D2D_SMART_PTR(ID2D1Geometry, cpGeometry); - E2D_DECLARE_D2D_SMART_PTR(ID2D1PathGeometry, cpPathGeometry); - E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometrySink, cpGeometrySink); E2D_DECLARE_D2D_SMART_PTR(IDWriteTextFormat, cpTextFormat); E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, cpTextLayout); @@ -59,11 +64,13 @@ namespace easy2d if (ptr) { ptr->Release(); } } - inline void SafeRelease(IUnknown* ptr) + template + inline void SafeRelease(T*& ptr) { if (ptr != nullptr) { ptr->Release(); + ptr = nullptr; } } } diff --git a/core/base/render.cpp b/core/base/render.cpp index 7b06751b..5ac1c41c 100644 --- a/core/base/render.cpp +++ b/core/base/render.cpp @@ -168,41 +168,62 @@ namespace easy2d bitmap_cache_.clear(); } - HRESULT GraphicsDevice::CreateRectGeometry( - cpGeometry& geometry, - const math::Matrix& matrix, - const Size& size + HRESULT GraphicsDevice::CreateRectangleGeometry(cpRectangleGeometry & geo, Rect const& rect) const + { + if (!d2d.factory) + return E_UNEXPECTED; + + cpRectangleGeometry rectangle; + HRESULT hr = d2d.factory->CreateRectangleGeometry( + rect, + &rectangle + ); + + if (SUCCEEDED(hr)) + geo = rectangle; + return hr; + } + + HRESULT GraphicsDevice::CreateEllipseGeometry(cpEllipseGeometry & geo, Point const & center, float radius_x, float radius_y) const + { + if (!d2d.factory) + return E_UNEXPECTED; + + cpEllipseGeometry ellipse; + HRESULT hr = d2d.factory->CreateEllipseGeometry( + D2D1::Ellipse( + center, + radius_x, + radius_y + ), + &ellipse + ); + + if (SUCCEEDED(hr)) + geo = ellipse; + return hr; + } + + HRESULT GraphicsDevice::CreateTransformedGeometry( + cpTransformedGeometry& transformed, + math::Matrix const& matrix, + cpGeometry const& geo ) const { if (!d2d.factory) return E_UNEXPECTED; - HRESULT hr; - - ID2D1RectangleGeometry * rectangle = nullptr; - ID2D1TransformedGeometry * transformed = nullptr; - - hr = d2d.factory->CreateRectangleGeometry( - D2D1::RectF(0, 0, size.width, size.height), - &rectangle + cpTransformedGeometry transformed_tmp; + HRESULT hr = d2d.factory->CreateTransformedGeometry( + geo.Get(), + ConvertToD2DMatrix(matrix), + &transformed_tmp ); if (SUCCEEDED(hr)) { - hr = d2d.factory->CreateTransformedGeometry( - rectangle, - ConvertToD2DMatrix(matrix), - &transformed - ); + transformed = transformed_tmp; } - - if (SUCCEEDED(hr)) - { - geometry = transformed; - } - - SafeRelease(rectangle); - SafeRelease(transformed); return hr; } @@ -375,7 +396,7 @@ namespace easy2d HRESULT GraphicsDevice::DrawGeometry( cpGeometry const& geometry, - Color const& border_color, + Color const& stroke_color, float stroke_width, StrokeStyle stroke ) @@ -387,7 +408,7 @@ namespace easy2d if (window_occluded) return S_OK; - d2d.solid_brush->SetColor(border_color); + d2d.solid_brush->SetColor(stroke_color); d2d.render_target->DrawGeometry( geometry.Get(), d2d.solid_brush.Get(), @@ -397,6 +418,23 @@ namespace easy2d return S_OK; } + HRESULT GraphicsDevice::FillGeometry(cpGeometry const & geometry, const Color & fill_color) + { + if (!d2d.solid_brush || + !d2d.render_target) + return E_UNEXPECTED; + + if (window_occluded) + return S_OK; + + d2d.solid_brush->SetColor(fill_color); + d2d.render_target->FillGeometry( + geometry.Get(), + d2d.solid_brush.Get() + ); + return S_OK; + } + HRESULT GraphicsDevice::DrawImage(spImage const & image) { if (!d2d.render_target) @@ -833,5 +871,6 @@ namespace easy2d ); } } + } } diff --git a/core/base/render.h b/core/base/render.h index e57ff1c2..d8d83eba 100644 --- a/core/base/render.h +++ b/core/base/render.h @@ -68,10 +68,22 @@ namespace easy2d void CreateDeviceResources(HWND hwnd); - HRESULT CreateRectGeometry( - cpGeometry& geometry, - const math::Matrix& matrix, - const Size& size + HRESULT CreateRectangleGeometry( + cpRectangleGeometry& geo, + Rect const& rect + ) const; + + HRESULT CreateEllipseGeometry( + cpEllipseGeometry& geo, + Point const& center, + float radius_x, + float radius_y + ) const; + + HRESULT CreateTransformedGeometry( + cpTransformedGeometry& transformed, + math::Matrix const& matrix, + cpGeometry const& geo ) const; HRESULT CreatePathGeometry( @@ -142,11 +154,16 @@ namespace easy2d HRESULT DrawGeometry( cpGeometry const& geometry, - const Color& border_color, + const Color& stroke_color, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter ); + HRESULT FillGeometry( + cpGeometry const& geometry, + const Color& fill_color + ); + HRESULT DrawImage( spImage const& image ); diff --git a/core/easy2d.h b/core/easy2d.h index 973d7210..1c69739d 100644 --- a/core/easy2d.h +++ b/core/easy2d.h @@ -55,12 +55,15 @@ #include "base/RefCounter.hpp" #include "base/ObjectBase.h" +#include "base/Unit.h" +#include "base/Geometry.h" #include "base/Image.h" #include "base/Node.h" #include "base/Scene.h" #include "base/Sprite.h" #include "base/Text.h" #include "base/Canvas.h" +#include "base/GeometryNode.h" #include "base/Music.h" #include "base/Task.h" #include "base/Action.hpp" diff --git a/project/vs2013/Easy2D.vcxproj b/project/vs2013/Easy2D.vcxproj index d41d84fb..26fc37cb 100644 --- a/project/vs2013/Easy2D.vcxproj +++ b/project/vs2013/Easy2D.vcxproj @@ -34,6 +34,8 @@ + + @@ -64,6 +66,7 @@ + @@ -90,6 +93,8 @@ + + @@ -109,6 +114,7 @@ + diff --git a/project/vs2013/Easy2D.vcxproj.filters b/project/vs2013/Easy2D.vcxproj.filters index d3c7f541..af750553 100644 --- a/project/vs2013/Easy2D.vcxproj.filters +++ b/project/vs2013/Easy2D.vcxproj.filters @@ -176,6 +176,15 @@ base + + base + + + base + + + base + @@ -312,5 +321,14 @@ base + + base + + + base + + + base + \ No newline at end of file diff --git a/project/vs2015/Easy2D.vcxproj b/project/vs2015/Easy2D.vcxproj index 56456772..e1ac5c75 100644 --- a/project/vs2015/Easy2D.vcxproj +++ b/project/vs2015/Easy2D.vcxproj @@ -34,6 +34,8 @@ + + @@ -64,6 +66,7 @@ + @@ -90,6 +93,8 @@ + + @@ -109,6 +114,7 @@ + diff --git a/project/vs2015/Easy2D.vcxproj.filters b/project/vs2015/Easy2D.vcxproj.filters index d3c7f541..af750553 100644 --- a/project/vs2015/Easy2D.vcxproj.filters +++ b/project/vs2015/Easy2D.vcxproj.filters @@ -176,6 +176,15 @@ base + + base + + + base + + + base + @@ -312,5 +321,14 @@ base + + base + + + base + + + base + \ No newline at end of file diff --git a/project/vs2017/Easy2D.vcxproj b/project/vs2017/Easy2D.vcxproj index 5fc0e0bc..88e98062 100644 --- a/project/vs2017/Easy2D.vcxproj +++ b/project/vs2017/Easy2D.vcxproj @@ -34,6 +34,8 @@ + + @@ -64,6 +66,7 @@ + @@ -90,6 +93,8 @@ + + @@ -109,6 +114,7 @@ + diff --git a/project/vs2017/Easy2D.vcxproj.filters b/project/vs2017/Easy2D.vcxproj.filters index d3c7f541..af750553 100644 --- a/project/vs2017/Easy2D.vcxproj.filters +++ b/project/vs2017/Easy2D.vcxproj.filters @@ -176,6 +176,15 @@ base + + base + + + base + + + base + @@ -312,5 +321,14 @@ base + + base + + + base + + + base + \ No newline at end of file