add: geometries supported

This commit is contained in:
Haibo 2018-11-20 01:20:06 +08:00 committed by Nomango
parent ff8b647d9d
commit 2c7ccb4f6d
23 changed files with 1282 additions and 366 deletions

View File

@ -94,14 +94,13 @@ namespace easy2d
if (target) if (target)
{ {
Point currentPos = target->GetPosition(); Point diff = target->GetPosition() - prev_pos_;
Point diff = currentPos - prev_pos_;
start_pos_ = start_pos_ + diff; start_pos_ = start_pos_ + diff;
Point newPos = start_pos_ + (delta_pos_ * process_); Point new_pos = start_pos_ + (delta_pos_ * process_);
target->SetPosition(newPos); target->SetPosition(new_pos);
prev_pos_ = newPos; prev_pos_ = new_pos;
} }
} }
@ -176,15 +175,13 @@ namespace easy2d
float y = height_ * 4 * frac * (1 - frac); float y = height_ * 4 * frac * (1 - frac);
y += delta_pos_.y * process_; y += delta_pos_.y * process_;
Point currentPos = target->GetPosition(); Point diff = target->GetPosition() - prev_pos_;
Point diff = currentPos - prev_pos_;
start_pos_ = diff + start_pos_; start_pos_ = diff + start_pos_;
Point newPos = start_pos_ + Point(x, y); Point new_pos = start_pos_ + Point(x, y);
target->SetPosition(newPos); target->SetPosition(new_pos);
prev_pos_ = newPos; prev_pos_ = new_pos;
} }
} }

291
core/base/Geometry.cpp Normal file
View File

@ -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(&current_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<Point> const& points)
{
if (current_sink_)
{
if (!points.empty())
{
size_t size = points.size();
std::vector<D2D1_POINT_2F> d2d_points(size);
for (size_t i = 0; i < size; ++i)
{
d2d_points[i] = points[i];
}
current_sink_->AddLines(
&d2d_points[0],
static_cast<UINT32>(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;
}
}

188
core/base/Geometry.h Normal file
View File

@ -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<Point> const& points
);
// 添加一条三次方贝塞尔曲线
void AddBezier(
Point const& point1, /* 贝塞尔曲线的第一个控制点 */
Point const& point2, /* 贝塞尔曲线的第二个控制点 */
Point const& point3 /* 贝塞尔曲线的终点 */
);
// 清除路径
void ClearPath();
protected:
cpPathGeometry current_geometry_;
cpGeometrySink current_sink_;
};
}

View File

@ -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();
}
}
}

92
core/base/GeometryNode.h Normal file
View File

@ -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_;
};
}

View File

@ -44,18 +44,16 @@ namespace easy2d
, parent_(nullptr) , parent_(nullptr)
, hash_name_(0) , hash_name_(0)
, dirty_sort_(false) , dirty_sort_(false)
, dirty_transform_(false)
, order_(0) , order_(0)
, transform_()
, opacity_(1.f) , opacity_(1.f)
, display_opacity_(1.f) , display_opacity_(1.f)
, children_() , children_()
, border_color_(Color::Red, 0.6f)
, initial_matrix_() , initial_matrix_()
, final_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() Node::~Node()
@ -160,13 +158,24 @@ namespace easy2d
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f); devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f);
} }
for (auto child = children_.First(); child; child = child->NextItem()) DrawChildrenBorder();
{
child->DrawBorder();
}
} }
} }
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() void Node::UpdateTransform()
{ {
if (!dirty_transform_) if (!dirty_transform_)
@ -174,9 +183,14 @@ namespace easy2d
dirty_transform_ = false; 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( 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_) if (parent_)
@ -185,10 +199,7 @@ namespace easy2d
final_matrix_ = final_matrix_ * parent_->initial_matrix_; final_matrix_ = final_matrix_ * parent_->initial_matrix_;
} }
// 重新构造轮廓 UpdateBorder();
ThrowIfFailed(
devices::Graphics::Instance()->CreateRectGeometry(border_, final_matrix_, transform_.size)
);
for (auto child = children_.First(); child; child = child->NextItem()) 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) bool Node::Dispatch(const MouseEvent & e, bool handled)
{ {
if (visible_) 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) void Node::SetOpacity(float opacity)
{ {
if (opacity_ == opacity) if (opacity_ == opacity)
return; return;
display_opacity_ = opacity_ = std::min(std::max(opacity, 0.f), 1.f); display_opacity_ = opacity_ = std::min(std::max(opacity, 0.f), 1.f);
// 更新节点透明度
UpdateOpacity(); UpdateOpacity();
} }
void Node::SetPivotX(float pivot_x) 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) 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) 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; return;
transform_.pivot.x = pivot_x; pivot_.x = pivot_x;
transform_.pivot.y = pivot_y; pivot_.y = pivot_y;
dirty_transform_ = true; dirty_transform_ = true;
} }
void Node::SetWidth(float width) void Node::SetWidth(float width)
{ {
this->SetSize(width, transform_.size.height); this->SetSize(width, size_.height);
} }
void Node::SetHeight(float height) void Node::SetHeight(float height)
{ {
this->SetSize(transform_.size.width, height); this->SetSize(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;
} }
void Node::SetSize(const Size& size) void Node::SetSize(const Size& size)
@ -402,9 +336,14 @@ namespace easy2d
this->SetSize(size.width, size.height); 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) void Node::SetTransform(Transform const& transform)
@ -453,7 +392,7 @@ namespace easy2d
Rect Node::GetBounds() Rect Node::GetBounds()
{ {
return Rect(Point{}, transform_.size); return Rect(Point{}, size_);
} }
Node::Nodes Node::GetChildren(String const& name) const Node::Nodes Node::GetChildren(String const& name) const
@ -541,7 +480,7 @@ namespace easy2d
bool Node::ContainsPoint(const Point& point) 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; return false;
UpdateTransform(); UpdateTransform();
@ -549,34 +488,12 @@ namespace easy2d
BOOL ret = 0; BOOL ret = 0;
ThrowIfFailed( ThrowIfFailed(
border_->FillContainsPoint( border_->FillContainsPoint(
D2D1::Point2F(point.x, point.y), point,
D2D1::Matrix3x2F::Identity(), D2D1::Matrix3x2F::Identity(),
&ret &ret
) )
); );
return ret != 0; return !!ret;
}
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;
} }
void Node::SetVisible(bool val) void Node::SetVisible(bool val)

View File

@ -21,11 +21,11 @@
#pragma once #pragma once
#include "base.hpp" #include "base.hpp"
#include "time.h" #include "time.h"
#include "Unit.h"
#include "KeyEvent.h" #include "KeyEvent.h"
#include "MouseEvent.h" #include "MouseEvent.h"
#include "ActionManager.h" #include "ActionManager.h"
#include "TaskManager.h" #include "TaskManager.h"
#include "Transform.hpp"
#include "intrusive/List.hpp" #include "intrusive/List.hpp"
namespace easy2d namespace easy2d
@ -34,7 +34,7 @@ namespace easy2d
// 节点 // 节点
class Node class Node
: public ObjectBase : public Unit
, public ActionManager , public ActionManager
, public TaskManager , public TaskManager
, protected intrusive::ListItem<spNode> , protected intrusive::ListItem<spNode>
@ -58,164 +58,55 @@ namespace easy2d
// 更新节点 // 更新节点
virtual void OnUpdate(Duration const& dt) {} virtual void OnUpdate(Duration const& dt) {}
// 获取节点显示状态 // 获取显示状态
bool IsVisible() const { return visible_; } bool IsVisible() const { return visible_; }
// 获取节点名称 // 获取名称
String const& GetName() const { return name_; } String const& GetName() const { return name_; }
// 获取节点名称的 Hash 值 // 获取名称的 Hash 值
size_t GetHashName() const { return hash_name_; } size_t GetHashName() const { return hash_name_; }
// 获取节点绘图顺序 // 获取绘图顺序
int GetOrder() const { return order_; } 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() }; } Size GetSize() const { return Size{ GetWidth(), GetHeight() }; }
// 获取节点的支点 // 获取 x 方向支点
virtual float GetPivotX() const { return transform_.pivot.x; } virtual float GetPivotX() const { return pivot_.x; }
// 获取节点的支点 // 获取 y 方向支点
virtual float GetPivotY() const { return transform_.pivot.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 float GetOpacity() const { return opacity_; }
// 获取包围盒 // 获取包围盒
virtual Rect GetBounds(); virtual Rect GetBounds();
// 获取二维变换矩阵
virtual math::Matrix const& GetTransformMatrix() override;
// 获取父节点 // 获取父节点
virtual spNode GetParent() const { return parent_; } virtual spNode GetParent() const { return parent_; }
// 设置节点是否显示 // 设置是否显示
void SetVisible( void SetVisible(
bool val bool val
); );
// 设置节点名称 // 设置名称
void SetName( void SetName(
String const& name 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] // 默认为 0, 范围 [0, 1]
void SetPivotX( void SetPivotX(
@ -235,36 +126,46 @@ namespace easy2d
float pivot_y float pivot_y
); );
// 修改节点宽度 // 修改宽度
void SetWidth( void SetWidth(
float width float width
); );
// 修改节点高度 // 修改高度
void SetHeight( void SetHeight(
float height float height
); );
// 修改节点大小 // 修改大小
void SetSize( void SetSize(
float width, float width,
float height float height
); );
// 修改节点大小 // 修改大小
void SetSize( void SetSize(
const Size & size const Size & size
); );
// 设置节点边缘颜色 virtual void SetTransform(
void SetBorderColor( Transform const& transform
const Color& color ) 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 const Point& point
); );
// 判断两物体是否相交
bool Intersects(
spNode const& node
);
// 添加子节点 // 添加子节点
void AddChild( void AddChild(
spNode const& child, spNode const& child,
@ -340,12 +236,16 @@ namespace easy2d
protected: protected:
virtual void Update(Duration const& dt); virtual void Update(Duration const& dt);
virtual void DrawBorder();
void DrawChildrenBorder();
void UpdateBorder();
void UpdateTransform(); void UpdateTransform();
void UpdateOpacity(); void UpdateOpacity();
void DrawBorder();
protected: protected:
String name_; String name_;
size_t hash_name_; size_t hash_name_;
@ -354,12 +254,12 @@ namespace easy2d
int order_; int order_;
bool visible_; bool visible_;
bool dirty_sort_; bool dirty_sort_;
bool dirty_transform_;
Node* parent_; Node* parent_;
Color border_color_; Color border_color_;
Children children_; Children children_;
cpGeometry border_; cpGeometry border_;
Transform transform_; Point pivot_;
Size size_;
math::Matrix initial_matrix_; math::Matrix initial_matrix_;
math::Matrix final_matrix_; math::Matrix final_matrix_;
}; };

View File

@ -30,7 +30,7 @@ namespace easy2d
// ResourceData data; // ResourceData data;
// if (res.Load(&data)) { // if (res.Load(&data)) {
// LPVOID data = data.buffer; // LPVOID data = data.buffer;
// DWORD size = data.buffer_size; // DWORD size_ = data.buffer_size;
// } // }
// //
struct ResourceData struct ResourceData

View File

@ -29,40 +29,25 @@ namespace easy2d
class Transform class Transform
{ {
public: public:
Size size; // ´óС
float rotation; // Ðýת float rotation; // Ðýת
Point position; // ×ø±ê Point position; // ×ø±ê
Point scale; // Ëõ·Å Point scale; // Ëõ·Å
Point skew; // ´íÇÐ½Ç¶È Point skew; // ´íÇнǶÈ
Point pivot; // Ö§µã
public: public:
Transform() Transform()
: position() : position()
, size()
, rotation(0) , rotation(0)
, scale(1.f, 1.f) , scale(1.f, 1.f)
, skew(0.f, 0.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 bool operator== (const Transform& other) const
{ {
return position == other.position && return position == other.position &&
size == other.size &&
scale == other.scale && scale == other.scale &&
skew == other.skew && skew == other.skew &&
rotation == other.rotation && rotation == other.rotation;
pivot == other.pivot;
} }
}; };

View File

@ -106,7 +106,7 @@ namespace easy2d
if (out_scene_) if (out_scene_)
{ {
graphics->PushClip( graphics->PushClip(
out_scene_->GetTransform().ToMatrix(), out_scene_->GetTransformMatrix(),
window_size_ window_size_
); );
graphics->PushLayer(out_layer_, out_layer_prop_); graphics->PushLayer(out_layer_, out_layer_prop_);
@ -120,7 +120,7 @@ namespace easy2d
if (in_scene_) if (in_scene_)
{ {
graphics->PushClip( graphics->PushClip(
in_scene_->GetTransform().ToMatrix(), in_scene_->GetTransformMatrix(),
window_size_ window_size_
); );
graphics->PushLayer(in_layer_, in_layer_prop_); graphics->PushLayer(in_layer_, in_layer_prop_);
@ -332,17 +332,18 @@ namespace easy2d
Transition::Init(prev, next); Transition::Init(prev, next);
auto transform = Transform{}; auto transform = Transform{};
transform.pivot = Point{ 0.5f, 0.5f };
transform.position = Point{ window_size_.width / 2, window_size_.height / 2 }; transform.position = Point{ window_size_.width / 2, window_size_.height / 2 };
if (out_scene_) if (out_scene_)
{ {
out_scene_->SetTransform(transform); out_scene_->SetTransform(transform);
out_scene_->SetPivot(0.5f, 0.5f);
} }
if (in_scene_) if (in_scene_)
{ {
in_scene_->SetTransform(transform); in_scene_->SetTransform(transform);
in_scene_->SetPivot(0.5f, 0.5f);
} }
in_layer_prop_.opacity = 0; in_layer_prop_.opacity = 0;
@ -383,11 +384,13 @@ namespace easy2d
if (out_scene_) if (out_scene_)
{ {
out_scene_->SetTransform(Transform{}); out_scene_->SetTransform(Transform{});
out_scene_->SetPivot(0.f, 0.f);
} }
if (in_scene_) if (in_scene_)
{ {
in_scene_->SetTransform(Transform{}); in_scene_->SetTransform(Transform{});
in_scene_->SetPivot(0.f, 0.f);
} }
} }
} }

148
core/base/Unit.cpp Normal file
View File

@ -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);
}
}

152
core/base/Unit.h Normal file
View File

@ -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_;
};
}

View File

@ -44,11 +44,18 @@ namespace easy2d
E2D_DECLARE_SMART_PTR(Music); E2D_DECLARE_SMART_PTR(Music);
E2D_DECLARE_SMART_PTR(Task); 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(Node);
E2D_DECLARE_SMART_PTR(Scene); E2D_DECLARE_SMART_PTR(Scene);
E2D_DECLARE_SMART_PTR(Sprite); E2D_DECLARE_SMART_PTR(Sprite);
E2D_DECLARE_SMART_PTR(Text); E2D_DECLARE_SMART_PTR(Text);
E2D_DECLARE_SMART_PTR(Canvas); E2D_DECLARE_SMART_PTR(Canvas);
E2D_DECLARE_SMART_PTR(GeometryNode);
E2D_DECLARE_SMART_PTR(Action); E2D_DECLARE_SMART_PTR(Action);
E2D_DECLARE_SMART_PTR(MoveBy); E2D_DECLARE_SMART_PTR(MoveBy);

View File

@ -41,11 +41,16 @@ namespace easy2d
E2D_DECLARE_D2D_SMART_PTR(ID2D1BitmapRenderTarget, cpBitmapRenderTarget); E2D_DECLARE_D2D_SMART_PTR(ID2D1BitmapRenderTarget, cpBitmapRenderTarget);
E2D_DECLARE_D2D_SMART_PTR(ID2D1StrokeStyle, cpStrokeStyle); 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(ID2D1Layer, cpLayer);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Bitmap, cpBitmap); 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(IDWriteTextFormat, cpTextFormat);
E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, cpTextLayout); E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, cpTextLayout);
@ -59,11 +64,13 @@ namespace easy2d
if (ptr) { ptr->Release(); } if (ptr) { ptr->Release(); }
} }
inline void SafeRelease(IUnknown* ptr) template <typename T>
inline void SafeRelease(T*& ptr)
{ {
if (ptr != nullptr) if (ptr != nullptr)
{ {
ptr->Release(); ptr->Release();
ptr = nullptr;
} }
} }
} }

View File

@ -168,41 +168,62 @@ namespace easy2d
bitmap_cache_.clear(); bitmap_cache_.clear();
} }
HRESULT GraphicsDevice::CreateRectGeometry( HRESULT GraphicsDevice::CreateRectangleGeometry(cpRectangleGeometry & geo, Rect const& rect) const
cpGeometry& geometry, {
const math::Matrix& matrix, if (!d2d.factory)
const Size& size 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 ) const
{ {
if (!d2d.factory) if (!d2d.factory)
return E_UNEXPECTED; return E_UNEXPECTED;
HRESULT hr; cpTransformedGeometry transformed_tmp;
HRESULT hr = d2d.factory->CreateTransformedGeometry(
ID2D1RectangleGeometry * rectangle = nullptr; geo.Get(),
ID2D1TransformedGeometry * transformed = nullptr; ConvertToD2DMatrix(matrix),
&transformed_tmp
hr = d2d.factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, size.width, size.height),
&rectangle
); );
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d2d.factory->CreateTransformedGeometry( transformed = transformed_tmp;
rectangle,
ConvertToD2DMatrix(matrix),
&transformed
);
} }
if (SUCCEEDED(hr))
{
geometry = transformed;
}
SafeRelease(rectangle);
SafeRelease(transformed);
return hr; return hr;
} }
@ -375,7 +396,7 @@ namespace easy2d
HRESULT GraphicsDevice::DrawGeometry( HRESULT GraphicsDevice::DrawGeometry(
cpGeometry const& geometry, cpGeometry const& geometry,
Color const& border_color, Color const& stroke_color,
float stroke_width, float stroke_width,
StrokeStyle stroke StrokeStyle stroke
) )
@ -387,7 +408,7 @@ namespace easy2d
if (window_occluded) if (window_occluded)
return S_OK; return S_OK;
d2d.solid_brush->SetColor(border_color); d2d.solid_brush->SetColor(stroke_color);
d2d.render_target->DrawGeometry( d2d.render_target->DrawGeometry(
geometry.Get(), geometry.Get(),
d2d.solid_brush.Get(), d2d.solid_brush.Get(),
@ -397,6 +418,23 @@ namespace easy2d
return S_OK; 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) HRESULT GraphicsDevice::DrawImage(spImage const & image)
{ {
if (!d2d.render_target) if (!d2d.render_target)
@ -833,5 +871,6 @@ namespace easy2d
); );
} }
} }
} }
} }

View File

@ -68,10 +68,22 @@ namespace easy2d
void CreateDeviceResources(HWND hwnd); void CreateDeviceResources(HWND hwnd);
HRESULT CreateRectGeometry( HRESULT CreateRectangleGeometry(
cpGeometry& geometry, cpRectangleGeometry& geo,
const math::Matrix& matrix, Rect const& rect
const Size& size ) 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; ) const;
HRESULT CreatePathGeometry( HRESULT CreatePathGeometry(
@ -142,11 +154,16 @@ namespace easy2d
HRESULT DrawGeometry( HRESULT DrawGeometry(
cpGeometry const& geometry, cpGeometry const& geometry,
const Color& border_color, const Color& stroke_color,
float stroke_width, float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
); );
HRESULT FillGeometry(
cpGeometry const& geometry,
const Color& fill_color
);
HRESULT DrawImage( HRESULT DrawImage(
spImage const& image spImage const& image
); );

View File

@ -55,12 +55,15 @@
#include "base/RefCounter.hpp" #include "base/RefCounter.hpp"
#include "base/ObjectBase.h" #include "base/ObjectBase.h"
#include "base/Unit.h"
#include "base/Geometry.h"
#include "base/Image.h" #include "base/Image.h"
#include "base/Node.h" #include "base/Node.h"
#include "base/Scene.h" #include "base/Scene.h"
#include "base/Sprite.h" #include "base/Sprite.h"
#include "base/Text.h" #include "base/Text.h"
#include "base/Canvas.h" #include "base/Canvas.h"
#include "base/GeometryNode.h"
#include "base/Music.h" #include "base/Music.h"
#include "base/Task.h" #include "base/Task.h"
#include "base/Action.hpp" #include "base/Action.hpp"

View File

@ -34,6 +34,8 @@
<ClInclude Include="..\..\core\base\Debuger.h" /> <ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Geometry.h" />
<ClInclude Include="..\..\core\base\GeometryNode.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" /> <ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" /> <ClInclude Include="..\..\core\base\intrusive\List.hpp" />
@ -64,6 +66,7 @@
<ClInclude Include="..\..\core\base\time.h" /> <ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transform.hpp" /> <ClInclude Include="..\..\core\base\Transform.hpp" />
<ClInclude Include="..\..\core\base\Transition.h" /> <ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\Unit.h" />
<ClInclude Include="..\..\core\base\window.h" /> <ClInclude Include="..\..\core\base\window.h" />
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />
<ClInclude Include="..\..\core\math\Matrix.hpp" /> <ClInclude Include="..\..\core\math\Matrix.hpp" />
@ -90,6 +93,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" /> <ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" /> <ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" /> <ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Geometry.cpp" />
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" /> <ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" /> <ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" /> <ClCompile Include="..\..\core\base\KeyEvent.cpp" />
@ -109,6 +114,7 @@
<ClCompile Include="..\..\core\base\TextRenderer.cpp" /> <ClCompile Include="..\..\core\base\TextRenderer.cpp" />
<ClCompile Include="..\..\core\base\time.cpp" /> <ClCompile Include="..\..\core\base\time.cpp" />
<ClCompile Include="..\..\core\base\Transition.cpp" /> <ClCompile Include="..\..\core\base\Transition.cpp" />
<ClCompile Include="..\..\core\base\Unit.cpp" />
<ClCompile Include="..\..\core\base\window.cpp" /> <ClCompile Include="..\..\core\base\window.cpp" />
<ClCompile Include="..\..\core\math\rand.cpp" /> <ClCompile Include="..\..\core\math\rand.cpp" />
<ClCompile Include="..\..\core\ui\Button.cpp" /> <ClCompile Include="..\..\core\ui\Button.cpp" />

View File

@ -176,6 +176,15 @@
<ClInclude Include="..\..\core\base\ObjectBase.h"> <ClInclude Include="..\..\core\base\ObjectBase.h">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\Geometry.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\GeometryNode.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Unit.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">
@ -312,5 +321,14 @@
<ClCompile Include="..\..\core\base\ObjectBase.cpp"> <ClCompile Include="..\..\core\base\ObjectBase.cpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\base\Geometry.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\GeometryNode.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Unit.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -34,6 +34,8 @@
<ClInclude Include="..\..\core\base\Debuger.h" /> <ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Geometry.h" />
<ClInclude Include="..\..\core\base\GeometryNode.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" /> <ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" /> <ClInclude Include="..\..\core\base\intrusive\List.hpp" />
@ -64,6 +66,7 @@
<ClInclude Include="..\..\core\base\time.h" /> <ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transform.hpp" /> <ClInclude Include="..\..\core\base\Transform.hpp" />
<ClInclude Include="..\..\core\base\Transition.h" /> <ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\Unit.h" />
<ClInclude Include="..\..\core\base\window.h" /> <ClInclude Include="..\..\core\base\window.h" />
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />
<ClInclude Include="..\..\core\math\Matrix.hpp" /> <ClInclude Include="..\..\core\math\Matrix.hpp" />
@ -90,6 +93,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" /> <ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" /> <ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" /> <ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Geometry.cpp" />
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" /> <ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" /> <ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" /> <ClCompile Include="..\..\core\base\KeyEvent.cpp" />
@ -109,6 +114,7 @@
<ClCompile Include="..\..\core\base\TextRenderer.cpp" /> <ClCompile Include="..\..\core\base\TextRenderer.cpp" />
<ClCompile Include="..\..\core\base\time.cpp" /> <ClCompile Include="..\..\core\base\time.cpp" />
<ClCompile Include="..\..\core\base\Transition.cpp" /> <ClCompile Include="..\..\core\base\Transition.cpp" />
<ClCompile Include="..\..\core\base\Unit.cpp" />
<ClCompile Include="..\..\core\base\window.cpp" /> <ClCompile Include="..\..\core\base\window.cpp" />
<ClCompile Include="..\..\core\math\rand.cpp" /> <ClCompile Include="..\..\core\math\rand.cpp" />
<ClCompile Include="..\..\core\ui\Button.cpp" /> <ClCompile Include="..\..\core\ui\Button.cpp" />

View File

@ -176,6 +176,15 @@
<ClInclude Include="..\..\core\base\ObjectBase.h"> <ClInclude Include="..\..\core\base\ObjectBase.h">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\Geometry.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\GeometryNode.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Unit.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">
@ -312,5 +321,14 @@
<ClCompile Include="..\..\core\base\ObjectBase.cpp"> <ClCompile Include="..\..\core\base\ObjectBase.cpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\base\Geometry.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\GeometryNode.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Unit.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -34,6 +34,8 @@
<ClInclude Include="..\..\core\base\Debuger.h" /> <ClInclude Include="..\..\core\base\Debuger.h" />
<ClInclude Include="..\..\core\base\Font.hpp" /> <ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" /> <ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Geometry.h" />
<ClInclude Include="..\..\core\base\GeometryNode.h" />
<ClInclude Include="..\..\core\base\Image.h" /> <ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" /> <ClInclude Include="..\..\core\base\Input.h" />
<ClInclude Include="..\..\core\base\intrusive\List.hpp" /> <ClInclude Include="..\..\core\base\intrusive\List.hpp" />
@ -64,6 +66,7 @@
<ClInclude Include="..\..\core\base\time.h" /> <ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transform.hpp" /> <ClInclude Include="..\..\core\base\Transform.hpp" />
<ClInclude Include="..\..\core\base\Transition.h" /> <ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\Unit.h" />
<ClInclude Include="..\..\core\base\window.h" /> <ClInclude Include="..\..\core\base\window.h" />
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />
<ClInclude Include="..\..\core\math\Matrix.hpp" /> <ClInclude Include="..\..\core\math\Matrix.hpp" />
@ -90,6 +93,8 @@
<ClCompile Include="..\..\core\base\Color.cpp" /> <ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Debuger.cpp" /> <ClCompile Include="..\..\core\base\Debuger.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" /> <ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Geometry.cpp" />
<ClCompile Include="..\..\core\base\GeometryNode.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" /> <ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" /> <ClCompile Include="..\..\core\base\Input.cpp" />
<ClCompile Include="..\..\core\base\KeyEvent.cpp" /> <ClCompile Include="..\..\core\base\KeyEvent.cpp" />
@ -109,6 +114,7 @@
<ClCompile Include="..\..\core\base\TextRenderer.cpp" /> <ClCompile Include="..\..\core\base\TextRenderer.cpp" />
<ClCompile Include="..\..\core\base\time.cpp" /> <ClCompile Include="..\..\core\base\time.cpp" />
<ClCompile Include="..\..\core\base\Transition.cpp" /> <ClCompile Include="..\..\core\base\Transition.cpp" />
<ClCompile Include="..\..\core\base\Unit.cpp" />
<ClCompile Include="..\..\core\base\window.cpp" /> <ClCompile Include="..\..\core\base\window.cpp" />
<ClCompile Include="..\..\core\math\rand.cpp" /> <ClCompile Include="..\..\core\math\rand.cpp" />
<ClCompile Include="..\..\core\ui\Button.cpp" /> <ClCompile Include="..\..\core\ui\Button.cpp" />

View File

@ -176,6 +176,15 @@
<ClInclude Include="..\..\core\base\ObjectBase.h"> <ClInclude Include="..\..\core\base\ObjectBase.h">
<Filter>base</Filter> <Filter>base</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\core\base\Geometry.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\GeometryNode.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Unit.h">
<Filter>base</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="base"> <Filter Include="base">
@ -312,5 +321,14 @@
<ClCompile Include="..\..\core\base\ObjectBase.cpp"> <ClCompile Include="..\..\core\base\ObjectBase.cpp">
<Filter>base</Filter> <Filter>base</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\base\Geometry.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\GeometryNode.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Unit.cpp">
<Filter>base</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>