From 671719fb34a7ed3aee4d6af57dfed23b298bcb5b Mon Sep 17 00:00:00 2001
From: Nomango <569629550@qq.com>
Date: Wed, 14 Aug 2019 21:38:37 +0800
Subject: [PATCH] Add Geometry && add GeometrySink && rename ActionPath to
ActionWalk
---
projects/kiwano.vcxproj | 6 +
projects/kiwano.vcxproj.filters | 18 ++
src/kiwano/2d/ShapeActor.cpp | 282 +++++----------------------
src/kiwano/2d/ShapeActor.h | 147 ++++----------
src/kiwano/2d/Sprite.cpp | 1 +
src/kiwano/2d/action/ActionDelay.cpp | 40 ++++
src/kiwano/2d/action/ActionDelay.h | 41 ++++
src/kiwano/2d/action/ActionHelper.h | 34 +++-
src/kiwano/2d/action/ActionTween.cpp | 232 ----------------------
src/kiwano/2d/action/ActionTween.h | 102 ----------
src/kiwano/2d/action/ActionWalk.cpp | 128 ++++++++++++
src/kiwano/2d/action/ActionWalk.h | 112 +++++++++++
src/kiwano/2d/include-forwards.h | 2 +-
src/kiwano/kiwano.h | 2 +
src/kiwano/renderer/Geometry.cpp | 203 +++++++++++++++++++
src/kiwano/renderer/Geometry.h | 126 ++++++++++++
src/kiwano/renderer/Image.h | 2 +-
src/kiwano/renderer/render.cpp | 155 ++++++++++++++-
src/kiwano/renderer/render.h | 35 +++-
19 files changed, 968 insertions(+), 700 deletions(-)
create mode 100644 src/kiwano/2d/action/ActionDelay.cpp
create mode 100644 src/kiwano/2d/action/ActionDelay.h
create mode 100644 src/kiwano/2d/action/ActionWalk.cpp
create mode 100644 src/kiwano/2d/action/ActionWalk.h
create mode 100644 src/kiwano/renderer/Geometry.cpp
create mode 100644 src/kiwano/renderer/Geometry.h
diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index 545fbfad..6ae1c33b 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -2,9 +2,11 @@
+
+
@@ -69,6 +71,7 @@
+
@@ -86,8 +89,10 @@
+
+
@@ -120,6 +125,7 @@
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index 47f84249..f70612b5 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -279,6 +279,15 @@
2d
+
+ renderer
+
+
+ 2d\action
+
+
+ 2d\action
+
@@ -425,5 +434,14 @@
2d
+
+ renderer
+
+
+ 2d\action
+
+
+ 2d\action
+
\ No newline at end of file
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index 8939ebda..1e4689b5 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -20,6 +20,7 @@
#include "ShapeActor.h"
#include "../base/logs.h"
+#include "../renderer/render.h"
namespace kiwano
{
@@ -31,7 +32,7 @@ namespace kiwano
{
}
- ShapeActor::ShapeActor(ComPtr geometry)
+ ShapeActor::ShapeActor(Geometry geometry)
: ShapeActor()
{
SetGeometry(geometry);
@@ -46,10 +47,7 @@ namespace kiwano
if (!geo_)
return Rect{};
- D2D1_RECT_F rect;
- // no matter it failed or not
- geo_->GetBounds(D2D1::Matrix3x2F::Identity(), &rect);
- return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top };
+ return geo_.GetBoundingBox(Matrix());
}
Rect ShapeActor::GetBoundingBox() const
@@ -57,63 +55,7 @@ namespace kiwano
if (!geo_)
return Rect{};
- D2D1_RECT_F rect;
- // no matter it failed or not
- geo_->GetBounds(DX::ConvertToMatrix3x2F(transform_matrix_), &rect);
- return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top };
- }
-
- float ShapeActor::GetLength()
- {
- float length = 0.f;
- if (geo_)
- {
- // no matter it failed or not
- geo_->ComputeLength(D2D1::Matrix3x2F::Identity(), &length);
- }
- return length;
- }
-
- bool ShapeActor::ComputePointAtLength(float length, Point& point, Vec2& tangent)
- {
- if (geo_)
- {
- if (SUCCEEDED(geo_->ComputePointAtLength(
- length,
- D2D1::Matrix3x2F::Identity(),
- DX::ConvertToPoint2F(&point),
- DX::ConvertToPoint2F(&tangent))))
- {
- return true;
- }
- }
- return false;
- }
-
- float ShapeActor::ComputeArea()
- {
- if (!geo_)
- return 0.f;
-
- float area = 0.f;
- // no matter it failed or not
- geo_->ComputeArea(D2D1::Matrix3x2F::Identity(), &area);
- return area;
- }
-
- bool ShapeActor::ContainsPoint(Point const& point)
- {
- if (!geo_)
- return false;
-
- BOOL ret = 0;
- // no matter it failed or not
- geo_->FillContainsPoint(
- DX::ConvertToPoint2F(point),
- D2D1::Matrix3x2F::Identity(),
- &ret
- );
- return !!ret;
+ return geo_.GetBoundingBox(GetTransformMatrix());
}
void ShapeActor::SetFillColor(const Color & color)
@@ -164,49 +106,23 @@ namespace kiwano
{
}
- LineActor::LineActor(Point const& begin, Point const& end)
+ LineActor::LineActor(Point const& end)
{
- SetLine(begin, end);
+ SetEndPoint(end);
}
LineActor::~LineActor()
{
}
- void LineActor::SetLine(Point const& begin, Point const& end)
+ void LineActor::SetEndPoint(Point const& end)
{
- ComPtr path_geo;
- ComPtr path_sink;
+ Renderer::GetInstance()->CreateLineGeometry(geo_, Point{}, end);
- HRESULT hr = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(&path_geo);
-
- if (SUCCEEDED(hr))
+ if (geo_)
{
- hr = path_geo->Open(&path_sink);
+ SetSize(end);
}
-
- if (SUCCEEDED(hr))
- {
- path_sink->BeginFigure(DX::ConvertToPoint2F(begin), D2D1_FIGURE_BEGIN_FILLED);
- path_sink->AddLine(DX::ConvertToPoint2F(end));
- path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
- hr = path_sink->Close();
- }
-
- if (SUCCEEDED(hr))
- {
- geo_ = path_geo;
- }
- }
-
- void LineActor::SetBegin(Point const& begin)
- {
- SetLine(begin, end_);
- }
-
- void LineActor::SetEnd(Point const& end)
- {
- SetLine(begin_, end);
}
@@ -218,29 +134,22 @@ namespace kiwano
{
}
- RectActor::RectActor(Rect const& rect)
+ RectActor::RectActor(Size const& size)
{
- SetRect(rect);
- }
-
- RectActor::RectActor(Point const& left_top, Size const& size)
- {
- SetRect(Rect{ left_top, size });
+ SetRectSize(size);
}
RectActor::~RectActor()
{
}
- void RectActor::SetRect(Rect const& rect)
+ void RectActor::SetRectSize(Size const& size)
{
- ComPtr geo;
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
+ Renderer::GetInstance()->CreateRectGeometry(geo_, Rect{ Point{}, size });
- if (SUCCEEDED(factory->CreateRectangleGeometry(DX::ConvertToRectF(rect), &geo)))
+ if (geo_)
{
- geo_ = geo;
- rect_ = rect;
+ SetSize(size);
}
}
@@ -250,47 +159,35 @@ namespace kiwano
//-------------------------------------------------------
RoundRectActor::RoundRectActor()
- : radius_x_(0.f)
- , radius_y_(0.f)
{
}
- RoundRectActor::RoundRectActor(Rect const& rect, float radius_x, float radius_y)
+ RoundRectActor::RoundRectActor(Size const& size, Vec2 const& radius)
{
- SetRoundedRect(rect, radius_x, radius_y);
+ SetRoundedRect(size, radius);
}
RoundRectActor::~RoundRectActor()
{
}
- void RoundRectActor::SetRadius(float radius_x, float radius_y)
+ void RoundRectActor::SetRadius(Vec2 const& radius)
{
- SetRoundedRect(rect_, radius_x, radius_y);
+ SetRoundedRect(size_, radius);
}
- void RoundRectActor::SetRect(Rect const& rect)
+ void RoundRectActor::SetRectSize(Size const& size)
{
- SetRoundedRect(rect, radius_x_, radius_y_);
+ SetRoundedRect(size, radius_);
}
- void RoundRectActor::SetRoundedRect(Rect const& rect, float radius_x, float radius_y)
+ void RoundRectActor::SetRoundedRect(Size const& size, Vec2 const& radius)
{
- ComPtr geo;
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
+ Renderer::GetInstance()->CreateRoundedRectGeometry(geo_, Rect{ Point{}, size }, radius);
- if (SUCCEEDED(factory->CreateRoundedRectangleGeometry(
- D2D1::RoundedRect(
- DX::ConvertToRectF(rect),
- radius_x,
- radius_y
- ),
- &geo)))
+ if (geo_)
{
- geo_ = geo;
- rect_ = rect;
- radius_x_ = radius_x;
- radius_y_ = radius_y;
+ SetSize(size);
}
}
@@ -304,9 +201,9 @@ namespace kiwano
{
}
- CircleActor::CircleActor(Point const& center, float radius)
+ CircleActor::CircleActor(float radius)
{
- SetCircle(center, radius);
+ SetRadius(radius);
}
CircleActor::~CircleActor()
@@ -315,29 +212,11 @@ namespace kiwano
void CircleActor::SetRadius(float radius)
{
- SetCircle(center_, radius);
- }
+ Renderer::GetInstance()->CreateEllipseGeometry(geo_, Point{}, Vec2{ radius, radius });
- void CircleActor::SetCenter(Point const& center)
- {
- SetCircle(center, radius_);
- }
-
- void CircleActor::SetCircle(Point const& center, float radius)
- {
- ComPtr geo;
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
-
- if (SUCCEEDED(factory->CreateEllipseGeometry(
- D2D1::Ellipse(
- DX::ConvertToPoint2F(center),
- radius,
- radius),
- &geo)))
+ if (geo_)
{
- geo_ = geo;
- center_ = center;
- radius_ = radius;
+ SetSize(radius * 2, radius * 2);
}
}
@@ -347,45 +226,25 @@ namespace kiwano
//-------------------------------------------------------
EllipseActor::EllipseActor()
- : radius_x_(0.f)
- , radius_y_(0.f)
{
}
- EllipseActor::EllipseActor(Point const& center, float radius_x, float radius_y)
+ EllipseActor::EllipseActor(Vec2 const& radius)
{
- SetEllipse(center, radius_x, radius_y);
+ SetRadius(radius);
}
EllipseActor::~EllipseActor()
{
}
- void EllipseActor::SetRadius(float radius_x, float radius_y)
+ void EllipseActor::SetRadius(Vec2 const& radius)
{
- SetEllipse(center_, radius_x, radius_y);
- }
+ Renderer::GetInstance()->CreateEllipseGeometry(geo_, Point{}, radius);
- void EllipseActor::SetCenter(Point const& center)
- {
- SetEllipse(center, radius_x_, radius_y_);
- }
-
- void EllipseActor::SetEllipse(Point const& center, float radius_x, float radius_y)
- {
- ComPtr geo;
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
-
- if (SUCCEEDED(factory->CreateEllipseGeometry(
- D2D1::Ellipse(
- DX::ConvertToPoint2F(center),
- radius_x,
- radius_y),
- &geo)))
+ if (geo_)
{
- geo_ = geo;
- radius_x_ = radius_x;
- radius_y_ = radius_y;
+ SetSize(radius * 2);
}
}
@@ -404,89 +263,38 @@ namespace kiwano
void PathActor::BeginPath(Point const& begin_pos)
{
- current_geometry_ = nullptr;
-
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
-
- ThrowIfFailed(
- factory->CreatePathGeometry(¤t_geometry_)
- );
-
- ThrowIfFailed(
- current_geometry_->Open(¤t_sink_)
- );
-
- current_sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
+ sink_.BeginPath(begin_pos);
}
void PathActor::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;
- }
+ sink_.EndPath(closed);
+ geo_ = sink_.GetGeometry();
}
void PathActor::AddLine(Point const& point)
{
- if (current_sink_)
- current_sink_->AddLine(DX::ConvertToPoint2F(point));
+ sink_.AddLine(point);
}
void PathActor::AddLines(Vector const& points)
{
- if (current_sink_ && !points.empty())
- {
- current_sink_->AddLines(
- reinterpret_cast(&points[0]),
- static_cast(points.size())
- );
- }
+ sink_.AddLines(points);
}
void PathActor::AddBezier(Point const& point1, Point const& point2, Point const& point3)
{
- if (current_sink_)
- {
- current_sink_->AddBezier(
- D2D1::BezierSegment(
- DX::ConvertToPoint2F(point1),
- DX::ConvertToPoint2F(point2),
- DX::ConvertToPoint2F(point3)
- )
- );
- }
+ sink_.AddBezier(point1, point2, point3);
}
void PathActor::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
{
- if (current_sink_)
- {
- current_sink_->AddArc(
- D2D1::ArcSegment(
- DX::ConvertToPoint2F(point),
- DX::ConvertToSizeF(radius),
- rotation,
- clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
- is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
- )
- );
- }
+ sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void PathActor::ClearPath()
{
- geo_ = nullptr;
- current_sink_ = nullptr;
- current_geometry_ = nullptr;
+ geo_.SetGeometry(nullptr);
}
}
diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h
index 25498b2e..940a34df 100644
--- a/src/kiwano/2d/ShapeActor.h
+++ b/src/kiwano/2d/ShapeActor.h
@@ -20,7 +20,7 @@
#pragma once
#include "Actor.h"
-#include "../renderer/render.h" // ID2D1Geometry
+#include "../renderer/Geometry.h"
namespace kiwano
{
@@ -32,7 +32,7 @@ namespace kiwano
ShapeActor();
ShapeActor(
- ComPtr geometry
+ Geometry geometry
);
virtual ~ShapeActor();
@@ -55,24 +55,6 @@ namespace kiwano
// 获取外切包围盒
Rect GetBoundingBox() const override;
- // 判断图形是否包含点
- bool ContainsPoint(
- Point const& point
- );
-
- // 获取图形展开成一条直线的长度
- float GetLength();
-
- // 计算面积
- float ComputeArea();
-
- // 计算图形路径上点的位置和切线向量
- bool ComputePointAtLength(
- float length,
- Point& point,
- Vec2& tangent
- );
-
// 设置填充颜色
void SetFillColor(
const Color& color
@@ -94,19 +76,19 @@ namespace kiwano
);
// 设置形状
- inline void SetGeometry(ComPtr geometry) { geo_ = geometry; }
+ inline void SetGeometry(Geometry geometry) { geo_ = geometry; }
// 获取形状
- inline ComPtr GetGeometry() const { return geo_; }
+ inline Geometry GetGeometry() const { return geo_; }
void OnRender(Renderer* renderer) override;
protected:
- Color fill_color_;
- Color stroke_color_;
- float stroke_width_;
- StrokeStyle outline_join_;
- ComPtr geo_;
+ Color fill_color_;
+ Color stroke_color_;
+ float stroke_width_;
+ StrokeStyle outline_join_;
+ Geometry geo_;
};
@@ -118,31 +100,18 @@ namespace kiwano
LineActor();
LineActor(
- Point const& begin,
- Point const& end
+ Point const& end_pos
);
virtual ~LineActor();
- Point const& GetBegin() const { return begin_; }
+ Point const& GetEndPoint() const { return end_; }
- Point const& GetEnd() const { return end_; }
-
- void SetLine(
- Point const& begin,
- Point const& end
- );
-
- void SetBegin(
- Point const& begin
- );
-
- void SetEnd(
+ void SetEndPoint(
Point const& end
);
protected:
- Point begin_;
Point end_;
};
@@ -155,22 +124,17 @@ namespace kiwano
RectActor();
RectActor(
- Rect const& rect
- );
-
- RectActor(
- Point const& left_top,
Size const& size
);
virtual ~RectActor();
- Rect const& GetRect() const { return rect_; }
+ void SetRectSize(Size const& size);
- void SetRect(Rect const& rect);
+ inline Size const& GetRectSize() const { return size_; }
protected:
- Rect rect_;
+ Size size_;
};
@@ -182,38 +146,32 @@ namespace kiwano
RoundRectActor();
RoundRectActor(
- Rect const& rect,
- float radius_x,
- float radius_y
+ Size const& size,
+ Vec2 const& radius
);
virtual ~RoundRectActor();
- float GetRadiusX() const { return radius_x_; }
-
- float GetRadiusY() const { return radius_y_; }
-
void SetRadius(
- float radius_x,
- float radius_y
+ Vec2 const& radius
);
- Rect const& GetRect() const { return rect_; }
-
- void SetRect(
- Rect const& rect
+ void SetRectSize(
+ Size const& size
);
void SetRoundedRect(
- Rect const& rect,
- float radius_x,
- float radius_y
+ Size const& size,
+ Vec2 const& radius
);
+ inline Vec2 GetRadius() const { return radius_; }
+
+ inline Size GetRectSize() const { return size_; }
+
protected:
- Rect rect_;
- float radius_x_;
- float radius_y_;
+ Size size_;
+ Vec2 radius_;
};
@@ -225,31 +183,16 @@ namespace kiwano
CircleActor();
CircleActor(
- Point const& center,
float radius
);
virtual ~CircleActor();
- float GetRadius() const { return radius_; }
+ inline float GetRadius() const { return radius_; }
- void SetRadius(
- float radius
- );
-
- Point const& GetCenter() const { return center_; }
-
- void SetCenter(
- Point const& center
- );
-
- void SetCircle(
- Point const& center,
- float radius
- );
+ void SetRadius(float radius);
protected:
- Point center_;
float radius_;
};
@@ -262,38 +205,19 @@ namespace kiwano
EllipseActor();
EllipseActor(
- Point const& center,
- float radius_x,
- float radius_y
+ Vec2 const& radius
);
virtual ~EllipseActor();
- float GetRadiusX() const { return radius_x_; }
-
- float GetRadiusY() const { return radius_y_; }
+ Vec2 GetRadius() const { return radius_; }
void SetRadius(
- float radius_x,
- float radius_y
- );
-
- Point const& GetCenter() const { return center_; }
-
- void SetCenter(
- Point const& center
- );
-
- void SetEllipse(
- Point const& center,
- float radius_x,
- float radius_y
+ Vec2 const& radius
);
protected:
- Point center_;
- float radius_x_;
- float radius_y_;
+ Vec2 radius_;
};
@@ -346,8 +270,7 @@ namespace kiwano
void ClearPath();
protected:
- ComPtr current_geometry_;
- ComPtr current_sink_;
+ GeometrySink sink_;
};
}
diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp
index 301747aa..0223fe08 100644
--- a/src/kiwano/2d/Sprite.cpp
+++ b/src/kiwano/2d/Sprite.cpp
@@ -88,6 +88,7 @@ namespace kiwano
if (frame_ && renderer->CheckVisibility(size_, transform_matrix_))
{
PrepareRender(renderer);
+
renderer->DrawBitmap(frame_->GetImage()->GetBitmap(), frame_->GetCropRect(), GetBounds());
}
}
diff --git a/src/kiwano/2d/action/ActionDelay.cpp b/src/kiwano/2d/action/ActionDelay.cpp
new file mode 100644
index 00000000..7f784431
--- /dev/null
+++ b/src/kiwano/2d/action/ActionDelay.cpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2016-2018 Kiwano - 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 "ActionDelay.h"
+
+namespace kiwano
+{
+ ActionDelay::ActionDelay(Duration delay)
+ {
+ SetDelay(delay);
+ }
+
+ ActionPtr ActionDelay::Clone() const
+ {
+ return new ActionDelay(delay_);
+ }
+
+ ActionPtr ActionDelay::Reverse() const
+ {
+ return new ActionDelay(delay_);
+ }
+
+}
diff --git a/src/kiwano/2d/action/ActionDelay.h b/src/kiwano/2d/action/ActionDelay.h
new file mode 100644
index 00000000..3c3dfd10
--- /dev/null
+++ b/src/kiwano/2d/action/ActionDelay.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2016-2018 Kiwano - 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 "Action.h"
+
+namespace kiwano
+{
+ // 延时动作
+ class KGE_API ActionDelay
+ : public Action
+ {
+ public:
+ ActionDelay(
+ Duration delay /* 持续时长 */
+ );
+
+ // 获取该动作的拷贝对象
+ ActionPtr Clone() const override;
+
+ // 获取该动作的倒转
+ ActionPtr Reverse() const override;
+ };
+}
diff --git a/src/kiwano/2d/action/ActionHelper.h b/src/kiwano/2d/action/ActionHelper.h
index 4735b1e6..c8d396f3 100644
--- a/src/kiwano/2d/action/ActionHelper.h
+++ b/src/kiwano/2d/action/ActionHelper.h
@@ -19,8 +19,10 @@
// THE SOFTWARE.
#pragma once
-#include "ActionGroup.h"
#include "ActionTween.h"
+#include "ActionWalk.h"
+#include "ActionDelay.h"
+#include "ActionGroup.h"
#include "Animation.h"
namespace kiwano
@@ -185,6 +187,32 @@ namespace kiwano
return TweenHelper(new kiwano::ActionRotateTo(dur, rotation));
}
+ static inline TweenHelper
+ Walk(
+ Duration duration, /* 持续时长 */
+ Geometry const& geo, /* 路线 */
+ bool rotating = false, /* 沿路线切线方向旋转 */
+ float start = 0.f, /* 起点 */
+ float end = 1.f, /* 终点 */
+ EaseFunc func = nullptr /* 速度变化 */
+ )
+ {
+ return TweenHelper(new kiwano::ActionWalk(duration, geo, rotating, start, end, func));
+ }
+
+ static inline TweenHelper
+ Walk(
+ Duration duration, /* 持续时长 */
+ GeometrySink& sink, /* 路线生成器 */
+ bool rotating = false, /* 沿路线切线方向旋转 */
+ float start = 0.f, /* 起点 */
+ float end = 1.f, /* 终点 */
+ EaseFunc func = nullptr /* 速度变化 */
+ )
+ {
+ return TweenHelper(new kiwano::ActionWalk(duration, sink.GetGeometry(), rotating, start, end, func));
+ }
+
static inline TweenHelper
Animation(Duration dur, FrameSequencePtr frames)
{
@@ -220,7 +248,7 @@ namespace kiwano
KGE_DEPRECATED("Tween::OpacityBy has been removed, use Tween::FadeTo instead")
static inline TweenHelper
- OpacityBy(float opacity)
+ OpacityBy(float opacity)
{
KGE_ASSERT("Tween::OpacityBy has been removed, use Tween::FadeTo instead");
return TweenHelper(nullptr);
@@ -242,7 +270,7 @@ namespace kiwano
KGE_DEPRECATED("Tween::Spawn is deprecated, use Tween::Multiple instead")
static inline ActionHelper
- Spawn(Vector const& actions)
+ Spawn(Vector const& actions)
{
return ActionHelper(new kiwano::ActionGroup(actions, false));
}
diff --git a/src/kiwano/2d/action/ActionTween.cpp b/src/kiwano/2d/action/ActionTween.cpp
index 0bb1e597..b78c8720 100644
--- a/src/kiwano/2d/action/ActionTween.cpp
+++ b/src/kiwano/2d/action/ActionTween.cpp
@@ -419,218 +419,6 @@ namespace kiwano
}
- //-------------------------------------------------------
- // ActionPath
- //-------------------------------------------------------
-
- ActionPath::ActionPath(Duration duration, bool rotating, float start, float end, EaseFunc func)
- : ActionTween(duration, func)
- , start_(start)
- , end_(end)
- , rotating_(rotating)
- , path_beginning_(false)
- , geo_(nullptr)
- , geo_sink_(nullptr)
- {
- }
-
- ActionPtr ActionPath::Clone() const
- {
- ActionPathPtr clone = new ActionPath(dur_, rotating_, start_, end_, ease_func_);
- if (clone)
- {
- clone->SetGeometry(geo_);
- }
- return clone;
- }
-
- ActionPtr ActionPath::Reverse() const
- {
- ActionPathPtr reverse = new ActionPath(dur_, rotating_, end_, start_, ease_func_);
- if (reverse)
- {
- reverse->SetGeometry(geo_);
- }
- return reverse;
- }
-
- float ActionPath::GetPathLength() const
- {
- float length = 0.f;
- if (geo_)
- {
- // no matter it failed or not
- geo_->ComputeLength(D2D1::Matrix3x2F::Identity(), &length);
- }
- return length;
- }
-
- bool ActionPath::ComputePointAtLength(float length, Point* point, Vec2* tangent) const
- {
- if (geo_)
- {
- HRESULT hr = geo_->ComputePointAtLength(
- length,
- D2D1::Matrix3x2F::Identity(),
- DX::ConvertToPoint2F(point),
- DX::ConvertToPoint2F(tangent)
- );
- return SUCCEEDED(hr);
- }
- return false;
- }
-
- void ActionPath::Init(ActorPtr target)
- {
- start_pos_ = target->GetPosition();
-
- if (path_beginning_)
- {
- EndPath();
- }
-
- if (!geo_)
- {
- Complete(target);
- }
- }
-
- void ActionPath::UpdateTween(ActorPtr target, float percent)
- {
- float length = GetPathLength() * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f);
-
- Point point, tangent;
- if (ComputePointAtLength(length, &point, &tangent))
- {
- target->SetPosition(start_pos_ + point);
-
- if (rotating_)
- {
- float ac = math::Acos(tangent.x);
- float rotation = (tangent.y < 0.f) ? 360.f - ac : ac;
- target->SetRotation(rotation);
- }
- }
- }
-
- void ActionPath::BeginPath()
- {
- if (path_beginning_) return;
- path_beginning_ = true;
-
- geo_ = nullptr;
- geo_sink_ = nullptr;
-
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory();
-
- ThrowIfFailed(
- factory->CreatePathGeometry(&geo_)
- );
-
- ThrowIfFailed(
- geo_->Open(&geo_sink_)
- );
-
- geo_sink_->BeginFigure(DX::ConvertToPoint2F(Point{ 0, 0 }), D2D1_FIGURE_BEGIN_FILLED);
- }
-
- void ActionPath::EndPath(bool closed)
- {
- if (!path_beginning_) return;
- path_beginning_ = false;
-
- if (geo_sink_)
- {
- geo_sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
- ThrowIfFailed(
- geo_sink_->Close()
- );
-
- // Clear geometry sink
- geo_sink_ = nullptr;
- }
- }
-
- void ActionPath::AddLine(Point const& point)
- {
- if (!path_beginning_)
- {
- BeginPath();
- }
-
- if (geo_sink_)
- {
- geo_sink_->AddLine(DX::ConvertToPoint2F(point));
- }
- }
-
- void ActionPath::AddLines(Vector const& points)
- {
- if (!path_beginning_)
- {
- BeginPath();
- }
-
- if (geo_sink_ && !points.empty())
- {
- geo_sink_->AddLines(
- reinterpret_cast(&points[0]),
- static_cast(points.size())
- );
- }
- }
-
- void ActionPath::AddBezier(Point const& point1, Point const& point2, Point const& point3)
- {
- if (!path_beginning_)
- {
- BeginPath();
- }
-
- if (geo_sink_)
- {
- geo_sink_->AddBezier(
- D2D1::BezierSegment(
- DX::ConvertToPoint2F(point1),
- DX::ConvertToPoint2F(point2),
- DX::ConvertToPoint2F(point3)
- )
- );
- }
- }
-
- void ActionPath::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
- {
- if (!path_beginning_)
- {
- BeginPath();
- }
-
- if (geo_sink_)
- {
- geo_sink_->AddArc(
- D2D1::ArcSegment(
- DX::ConvertToPoint2F(point),
- DX::ConvertToSizeF(radius),
- rotation,
- clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
- is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
- )
- );
- }
- }
-
- void ActionPath::ClearPath()
- {
- if (path_beginning_)
- {
- EndPath();
- }
-
- geo_sink_ = nullptr;
- geo_ = nullptr;
- }
-
//-------------------------------------------------------
// ActionCustom
//-------------------------------------------------------
@@ -658,24 +446,4 @@ namespace kiwano
tween_func_(target, percent);
}
-
- //-------------------------------------------------------
- // ActionDelay
- //-------------------------------------------------------
-
- ActionDelay::ActionDelay(Duration delay)
- {
- SetDelay(delay);
- }
-
- ActionPtr ActionDelay::Clone() const
- {
- return new ActionDelay(delay_);
- }
-
- ActionPtr ActionDelay::Reverse() const
- {
- return new ActionDelay(delay_);
- }
-
}
diff --git a/src/kiwano/2d/action/ActionTween.h b/src/kiwano/2d/action/ActionTween.h
index 43e7d240..46854a7c 100644
--- a/src/kiwano/2d/action/ActionTween.h
+++ b/src/kiwano/2d/action/ActionTween.h
@@ -21,7 +21,6 @@
#pragma once
#include "Action.h"
#include "../../base/logs.h"
-#include "../../renderer/render.h" // ID2D1PathGeometry, ID2D1GeometrySink
namespace kiwano
{
@@ -412,91 +411,6 @@ namespace kiwano
};
- // 路径动作
- class KGE_API ActionPath
- : public ActionTween
- {
- public:
- ActionPath(
- Duration duration, /* 持续时长 */
- bool rotating = false, /* 沿路径切线方向旋转 */
- float start = 0.f, /* 起点 */
- float end = 1.f, /* 终点 */
- EaseFunc func = nullptr /* 速度变化 */
- );
-
- // 获取该动作的拷贝对象
- ActionPtr Clone() const override;
-
- // 获取该动作的倒转
- ActionPtr Reverse() const override;
-
- // 开始添加路径
- void BeginPath();
-
- // 结束路径
- void EndPath(
- bool closed = false /* 路径是否闭合 */
- );
-
- // 添加一条线段
- void AddLine(
- Point const& point /* 端点 */
- );
-
- // 添加多条线段
- void AddLines(
- Vector const& points
- );
-
- // 添加一条三次方贝塞尔曲线
- void AddBezier(
- Point const& point1, /* 贝塞尔曲线的第一个控制点 */
- Point const& point2, /* 贝塞尔曲线的第二个控制点 */
- Point const& point3 /* 贝塞尔曲线的终点 */
- );
-
- // 添加弧线
- void AddArc(
- Point const& point, /* 终点 */
- Size const& radius, /* 椭圆半径 */
- float rotation, /* 椭圆旋转角度 */
- bool clockwise = true, /* 顺时针 or 逆时针 */
- bool is_small = true /* 是否取小于 180° 的弧 */
- );
-
- // 清除路径
- void ClearPath();
-
- // 获取路径长度
- float GetPathLength() const;
-
- // 计算当前路径上指定点坐标和切线
- bool ComputePointAtLength(float length, Point* point, Vec2* tangent) const;
-
- // 获取几何路径
- inline ComPtr GetGeometry() const { return geo_; }
-
- // 设置几何路径
- inline void SetGeometry(ComPtr geo) { geo_ = geo; }
-
- protected:
- void Init(ActorPtr target) override;
-
- void UpdateTween(ActorPtr target, float percent) override;
-
- protected:
- bool path_beginning_;
- bool rotating_;
- float start_;
- float end_;
- Point start_pos_;
-
- ComPtr geo_;
- ComPtr geo_sink_;
- };
-
-
// 自定义动作
class KGE_API ActionCustom
: public ActionTween
@@ -529,20 +443,4 @@ namespace kiwano
TweenFunc tween_func_;
};
-
- // 延时动作
- class KGE_API ActionDelay
- : public Action
- {
- public:
- ActionDelay(
- Duration delay /* 持续时长 */
- );
-
- // 获取该动作的拷贝对象
- ActionPtr Clone() const override;
-
- // 获取该动作的倒转
- ActionPtr Reverse() const override;
- };
}
diff --git a/src/kiwano/2d/action/ActionWalk.cpp b/src/kiwano/2d/action/ActionWalk.cpp
new file mode 100644
index 00000000..addf325e
--- /dev/null
+++ b/src/kiwano/2d/action/ActionWalk.cpp
@@ -0,0 +1,128 @@
+// Copyright (c) 2016-2018 Kiwano - 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 "ActionWalk.h"
+#include "../Actor.h"
+
+namespace kiwano
+{
+ ActionWalk::ActionWalk(Duration duration, bool rotating, float start, float end, EaseFunc func)
+ : ActionTween(duration, func)
+ , start_(start)
+ , end_(end)
+ , rotating_(rotating)
+ , length_(0.f)
+ {
+ }
+
+ ActionWalk::ActionWalk(Duration duration, Geometry const& path, bool rotating, float start, float end, EaseFunc func)
+ : ActionWalk(duration, rotating, start, end, func)
+ {
+ path_ = path;
+ }
+
+ ActionPtr ActionWalk::Clone() const
+ {
+ ActionWalkPtr clone = new ActionWalk(dur_, rotating_, start_, end_, ease_func_);
+ if (clone)
+ {
+ clone->SetPath(path_);
+ }
+ return clone;
+ }
+
+ ActionPtr ActionWalk::Reverse() const
+ {
+ ActionWalkPtr reverse = new ActionWalk(dur_, rotating_, end_, start_, ease_func_);
+ if (reverse)
+ {
+ reverse->SetPath(path_);
+ }
+ return reverse;
+ }
+
+ void ActionWalk::Init(ActorPtr target)
+ {
+ if (!path_)
+ {
+ Complete(target);
+ return;
+ }
+
+ start_pos_ = target->GetPosition();
+ length_ = path_.GetLength();
+ }
+
+ void ActionWalk::UpdateTween(ActorPtr target, float percent)
+ {
+ float distance = length_ * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f);
+
+ Point point, tangent;
+ if (path_.ComputePointAtLength(distance, point, tangent))
+ {
+ target->SetPosition(start_pos_ + point);
+
+ if (rotating_)
+ {
+ float ac = math::Acos(tangent.x);
+ float rotation = (tangent.y < 0.f) ? 360.f - ac : ac;
+ target->SetRotation(rotation);
+ }
+ }
+ KGE_LOG(L"%.2f, %.2f", target->GetPositionX(), target->GetPositionY());
+ }
+
+ void ActionWalk::BeginPath()
+ {
+ sink_.BeginPath();
+ }
+
+ void ActionWalk::EndPath(bool closed)
+ {
+ sink_.EndPath(closed);
+ path_ = sink_.GetGeometry();
+ }
+
+ void ActionWalk::AddLine(Point const& point)
+ {
+ sink_.AddLine(point);
+ }
+
+ void ActionWalk::AddLines(Vector const& points)
+ {
+ sink_.AddLines(points);
+ }
+
+ void ActionWalk::AddBezier(Point const& point1, Point const& point2, Point const& point3)
+ {
+ sink_.AddBezier(point1, point2, point3);
+ }
+
+ void ActionWalk::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
+ {
+ sink_.AddArc(point, radius, rotation, clockwise, is_small);
+ }
+
+ void ActionWalk::ClearPath()
+ {
+ path_.SetGeometry(nullptr);
+ }
+
+}
diff --git a/src/kiwano/2d/action/ActionWalk.h b/src/kiwano/2d/action/ActionWalk.h
new file mode 100644
index 00000000..f9747556
--- /dev/null
+++ b/src/kiwano/2d/action/ActionWalk.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2016-2018 Kiwano - 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 "ActionTween.h"
+#include "../../renderer/Geometry.h" // Geometry, GeometrySink
+
+namespace kiwano
+{
+ // 路线行走动作
+ class KGE_API ActionWalk
+ : public ActionTween
+ {
+ public:
+ ActionWalk(
+ Duration duration, /* 持续时长 */
+ bool rotating = false, /* 沿路线切线方向旋转 */
+ float start = 0.f, /* 起点 */
+ float end = 1.f, /* 终点 */
+ EaseFunc func = nullptr /* 速度变化 */
+ );
+
+ ActionWalk(
+ Duration duration, /* 持续时长 */
+ Geometry const& path, /* 路线 */
+ bool rotating = false, /* 沿路线切线方向旋转 */
+ float start = 0.f, /* 起点 */
+ float end = 1.f, /* 终点 */
+ EaseFunc func = nullptr /* 速度变化 */
+ );
+
+ // 获取该动作的拷贝对象
+ ActionPtr Clone() const override;
+
+ // 获取该动作的倒转
+ ActionPtr Reverse() const override;
+
+ // 开始添加路线
+ void BeginPath();
+
+ // 结束路线
+ void EndPath(
+ bool closed = false /* 路线是否闭合 */
+ );
+
+ // 添加一条线段
+ void AddLine(
+ Point const& point /* 端点 */
+ );
+
+ // 添加多条线段
+ void AddLines(
+ Vector const& points
+ );
+
+ // 添加一条三次方贝塞尔曲线
+ void AddBezier(
+ Point const& point1, /* 贝塞尔曲线的第一个控制点 */
+ Point const& point2, /* 贝塞尔曲线的第二个控制点 */
+ Point const& point3 /* 贝塞尔曲线的终点 */
+ );
+
+ // 添加弧线
+ void AddArc(
+ Point const& point, /* 终点 */
+ Size const& radius, /* 椭圆半径 */
+ float rotation, /* 椭圆旋转角度 */
+ bool clockwise = true, /* 顺时针 or 逆时针 */
+ bool is_small = true /* 是否取小于 180° 的弧 */
+ );
+
+ // 清除路径
+ void ClearPath();
+
+ // 获取路线
+ inline Geometry GetPath() const { return path_; }
+
+ // 设置路径
+ inline void SetPath(Geometry path) { path_ = path; }
+
+ protected:
+ void Init(ActorPtr target) override;
+
+ void UpdateTween(ActorPtr target, float percent) override;
+
+ protected:
+ bool rotating_;
+ float start_;
+ float end_;
+ float length_;
+ Point start_pos_;
+ Geometry path_;
+ GeometrySink sink_;
+ };
+}
diff --git a/src/kiwano/2d/include-forwards.h b/src/kiwano/2d/include-forwards.h
index 35f39f36..98f832e4 100644
--- a/src/kiwano/2d/include-forwards.h
+++ b/src/kiwano/2d/include-forwards.h
@@ -62,7 +62,7 @@ namespace kiwano
KGE_DECLARE_SMART_PTR(ActionFadeOut);
KGE_DECLARE_SMART_PTR(ActionRotateBy);
KGE_DECLARE_SMART_PTR(ActionRotateTo);
- KGE_DECLARE_SMART_PTR(ActionPath);
+ KGE_DECLARE_SMART_PTR(ActionWalk);
KGE_DECLARE_SMART_PTR(Animation);
KGE_DECLARE_SMART_PTR(ActionGroup);
KGE_DECLARE_SMART_PTR(ActionSpawn);
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index 6a2d0c7a..76c05fd6 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -92,6 +92,8 @@
#include "2d/action/Action.h"
#include "2d/action/ActionGroup.h"
#include "2d/action/ActionTween.h"
+#include "2d/action/ActionWalk.h"
+#include "2d/action/ActionDelay.h"
#include "2d/action/Animation.h"
#include "2d/action/ActionHelper.h"
#include "2d/action/ActionManager.h"
diff --git a/src/kiwano/renderer/Geometry.cpp b/src/kiwano/renderer/Geometry.cpp
new file mode 100644
index 00000000..2814ac8a
--- /dev/null
+++ b/src/kiwano/renderer/Geometry.cpp
@@ -0,0 +1,203 @@
+// Copyright (c) 2016-2018 Kiwano - 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 "../base/logs.h"
+
+namespace kiwano
+{
+
+ //
+ // Geometry
+ //
+
+ Geometry::Geometry()
+ {
+ }
+
+ Geometry::Geometry(ComPtr geo)
+ : geo_(geo)
+ {
+ }
+
+ Rect Geometry::GetBoundingBox(Matrix const& transform) const
+ {
+ if (!geo_)
+ return Rect{};
+
+ D2D1_RECT_F rect;
+ // no matter it failed or not
+ geo_->GetBounds(DX::ConvertToMatrix3x2F(transform), &rect);
+ return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top };
+ }
+
+ float Geometry::GetLength()
+ {
+ float length = 0.f;
+ if (geo_)
+ {
+ // no matter it failed or not
+ geo_->ComputeLength(D2D1::Matrix3x2F::Identity(), &length);
+ }
+ return length;
+ }
+
+ bool Geometry::ComputePointAtLength(float length, Point& point, Vec2& tangent)
+ {
+ if (geo_)
+ {
+ HRESULT hr = geo_->ComputePointAtLength(
+ length,
+ D2D1::Matrix3x2F::Identity(),
+ DX::ConvertToPoint2F(&point),
+ DX::ConvertToPoint2F(&tangent)
+ );
+
+ return SUCCEEDED(hr);
+ }
+ return false;
+ }
+
+ float Geometry::ComputeArea()
+ {
+ if (!geo_)
+ return 0.f;
+
+ float area = 0.f;
+ // no matter it failed or not
+ geo_->ComputeArea(D2D1::Matrix3x2F::Identity(), &area);
+ return area;
+ }
+
+ bool Geometry::ContainsPoint(Point const& point)
+ {
+ if (!geo_)
+ return false;
+
+ BOOL ret = 0;
+ // no matter it failed or not
+ geo_->FillContainsPoint(
+ DX::ConvertToPoint2F(point),
+ D2D1::Matrix3x2F::Identity(),
+ &ret
+ );
+ return !!ret;
+ }
+
+ //
+ // GeometrySink
+ //
+
+ GeometrySink::GeometrySink()
+ {
+ }
+
+ GeometrySink& GeometrySink::BeginPath(Point const& begin_pos)
+ {
+ if (!path_geo_)
+ {
+ Renderer::GetInstance()->CreatePathGeometrySink(*this);
+ }
+
+ if (!sink_)
+ {
+ ThrowIfFailed(path_geo_->Open(&sink_));
+ }
+
+ if (sink_)
+ {
+ sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
+ }
+ return (*this);
+ }
+
+ GeometrySink& GeometrySink::EndPath(bool closed)
+ {
+ if (sink_)
+ {
+ sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
+
+ ThrowIfFailed(sink_->Close());
+
+ sink_ = nullptr;
+ }
+ return (*this);
+ }
+
+ GeometrySink& GeometrySink::AddLine(Point const& point)
+ {
+ if (!sink_) BeginPath();
+
+ sink_->AddLine(DX::ConvertToPoint2F(point));
+ return (*this);
+ }
+
+ GeometrySink& GeometrySink::AddLines(Vector const& points)
+ {
+ if (!sink_) BeginPath();
+
+ sink_->AddLines(
+ reinterpret_cast(&points[0]),
+ static_cast(points.size())
+ );
+ return (*this);
+ }
+
+ GeometrySink& GeometrySink::AddBezier(Point const& point1, Point const& point2, Point const& point3)
+ {
+ if (!sink_) BeginPath();
+
+ sink_->AddBezier(
+ D2D1::BezierSegment(
+ DX::ConvertToPoint2F(point1),
+ DX::ConvertToPoint2F(point2),
+ DX::ConvertToPoint2F(point3)
+ )
+ );
+ return (*this);
+ }
+
+ GeometrySink& GeometrySink::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
+ {
+ if (!sink_) BeginPath();
+
+ sink_->AddArc(
+ D2D1::ArcSegment(
+ DX::ConvertToPoint2F(point),
+ DX::ConvertToSizeF(radius),
+ rotation,
+ clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
+ is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
+ )
+ );
+ return (*this);
+ }
+
+ Geometry GeometrySink::GetGeometry()
+ {
+ if (sink_)
+ {
+ EndPath();
+ }
+ return Geometry(path_geo_);
+ }
+
+}
diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h
new file mode 100644
index 00000000..0217dde9
--- /dev/null
+++ b/src/kiwano/renderer/Geometry.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2016-2018 Kiwano - 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/SmartPtr.hpp"
+#include "D2DDeviceResources.h"
+
+namespace kiwano
+{
+ // 几何体
+ class KGE_API Geometry
+ {
+ public:
+ // 获取外切包围盒
+ Rect GetBoundingBox(
+ Matrix const& transform = Matrix()
+ ) const;
+
+ // 判断图形是否包含点
+ bool ContainsPoint(
+ Point const& point
+ );
+
+ // 获取图形展开成一条直线的长度
+ float GetLength();
+
+ // 计算面积
+ float ComputeArea();
+
+ // 计算图形路径上点的位置和切线向量
+ bool ComputePointAtLength(
+ float length,
+ Point& point,
+ Vec2& tangent
+ );
+
+ public:
+ Geometry();
+
+ Geometry(ComPtr geo);
+
+ public:
+ inline ComPtr GetGeometry() const { return geo_; }
+
+ inline void SetGeometry(ComPtr geometry) { geo_ = geometry; }
+
+ inline operator bool() const { return static_cast(geo_); }
+
+ protected:
+ ComPtr geo_;
+ };
+
+
+ // 几何体生成器
+ class KGE_API GeometrySink
+ : protected noncopyable
+ {
+ public:
+ GeometrySink();
+
+ // 开始添加路径
+ GeometrySink& BeginPath(
+ Point const& begin_pos = Point{} /* 起始点 */
+ );
+
+ // 结束路径
+ GeometrySink& EndPath(
+ bool closed = false /* 路径是否闭合 */
+ );
+
+ // 添加一条线段
+ GeometrySink& AddLine(
+ Point const& point /* 端点 */
+ );
+
+ // 添加多条线段
+ GeometrySink& AddLines(
+ Vector const& points
+ );
+
+ // 添加一条三次方贝塞尔曲线
+ GeometrySink& AddBezier(
+ Point const& point1, /* 贝塞尔曲线的第一个控制点 */
+ Point const& point2, /* 贝塞尔曲线的第二个控制点 */
+ Point const& point3 /* 贝塞尔曲线的终点 */
+ );
+
+ // 添加弧线
+ GeometrySink& AddArc(
+ Point const& point, /* 终点 */
+ Size const& radius, /* 椭圆半径 */
+ float rotation, /* 椭圆旋转角度 */
+ bool clockwise = true, /* 顺时针 or 逆时针 */
+ bool is_small = true /* 是否取小于 180° 的弧 */
+ );
+
+ // 获取生成路径几何体
+ Geometry GetGeometry();
+
+ public:
+ inline ComPtr GetPathGeometry() const { return path_geo_; }
+
+ inline void SetPathGeometry(ComPtr path) { path_geo_ = path; }
+
+ protected:
+ ComPtr path_geo_;
+ ComPtr sink_;
+ };
+}
diff --git a/src/kiwano/renderer/Image.h b/src/kiwano/renderer/Image.h
index c3d6ee89..295d1e72 100644
--- a/src/kiwano/renderer/Image.h
+++ b/src/kiwano/renderer/Image.h
@@ -20,7 +20,7 @@
#pragma once
#include "../base/Resource.h"
-#include "render.h" // ID2D1Bitmap
+#include "D2DDeviceResources.h" // ID2D1Bitmap
namespace kiwano
{
diff --git a/src/kiwano/renderer/render.cpp b/src/kiwano/renderer/render.cpp
index 984855d3..3829fb2c 100644
--- a/src/kiwano/renderer/render.cpp
+++ b/src/kiwano/renderer/render.cpp
@@ -132,13 +132,16 @@ namespace kiwano
{
HRESULT hr = S_OK;
+ solid_color_brush_.reset();
hr = device_context_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
+ D2D1::BrushProperties(),
&solid_color_brush_
);
if (SUCCEEDED(hr))
{
+ text_renderer_.reset();
hr = ITextRenderer::Create(
&text_renderer_,
device_context_.get()
@@ -242,8 +245,144 @@ namespace kiwano
ThrowIfFailed(hr);
}
+ void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
+ {
+ HRESULT hr = S_OK;
+ if (!device_context_ || !d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr path_geo;
+ ComPtr path_sink;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = path_geo->Open(&path_sink);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
+ path_sink->AddLine(DX::ConvertToPoint2F(end_pos));
+ path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
+ hr = path_sink->Close();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ geo.SetGeometry(path_geo);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect)
+ {
+ HRESULT hr = S_OK;
+ if (!device_context_ || !d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetFactory()->CreateRectangleGeometry(DX::ConvertToRectF(rect), &output);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ geo.SetGeometry(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius)
+ {
+ HRESULT hr = S_OK;
+ if (!device_context_ || !d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetFactory()->CreateRoundedRectangleGeometry(
+ D2D1::RoundedRect(
+ DX::ConvertToRectF(rect),
+ radius.x,
+ radius.y
+ ),
+ &output);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ geo.SetGeometry(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius)
+ {
+ HRESULT hr = S_OK;
+ if (!device_context_ || !d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetFactory()->CreateEllipseGeometry(
+ D2D1::Ellipse(
+ DX::ConvertToPoint2F(center),
+ radius.x,
+ radius.y
+ ),
+ &output);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ geo.SetGeometry(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreatePathGeometrySink(GeometrySink& sink)
+ {
+ HRESULT hr = S_OK;
+ if (!device_context_ || !d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetFactory()->CreatePathGeometry(&output);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ sink.SetPathGeometry(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
void Renderer::DrawGeometry(
- ComPtr const& geometry,
+ Geometry const& geometry,
Color const& stroke_color,
float stroke_width,
StrokeStyle stroke
@@ -255,12 +394,12 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr) && geometry.GetGeometry())
{
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
device_context_->DrawGeometry(
- geometry.get(),
+ geometry.GetGeometry().get(),
solid_color_brush_.get(),
stroke_width,
d2d_res_->GetStrokeStyle(stroke)
@@ -272,7 +411,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::FillGeometry(ComPtr const & geometry, Color const& fill_color)
+ void Renderer::FillGeometry(Geometry const & geometry, Color const& fill_color)
{
HRESULT hr = S_OK;
if (!solid_color_brush_ || !device_context_)
@@ -280,11 +419,11 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr) && geometry.GetGeometry())
{
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
device_context_->FillGeometry(
- geometry.get(),
+ geometry.GetGeometry().get(),
solid_color_brush_.get()
);
}
@@ -292,7 +431,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::DrawRectangle(Rect const& rect, const Color& stroke_color, float stroke_width, StrokeStyle stroke)
+ void Renderer::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke)
{
HRESULT hr = S_OK;
if (!solid_color_brush_ || !device_context_)
@@ -437,7 +576,7 @@ namespace kiwano
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(),
properties.opacity,
- solid_color_brush_.get(),
+ nullptr,
D2D1_LAYER_OPTIONS_NONE
),
layer.get()
diff --git a/src/kiwano/renderer/render.h b/src/kiwano/renderer/render.h
index c796a363..50c9373c 100644
--- a/src/kiwano/renderer/render.h
+++ b/src/kiwano/renderer/render.h
@@ -27,8 +27,8 @@
#include "../2d/TextStyle.hpp"
#include "helper.hpp"
#include "Image.h"
+#include "Geometry.h"
#include "TextRenderer.h"
-#include "D2DDeviceResources.h"
#if defined(KGE_USE_DIRECTX10)
# include "D3D10DeviceResources.h"
@@ -56,21 +56,48 @@ namespace kiwano
ComPtr& layer
);
+ void CreateLineGeometry(
+ Geometry& geo,
+ Point const& begin_pos,
+ Point const& end_pos
+ );
+
+ void CreateRectGeometry(
+ Geometry& geo,
+ Rect const& rect
+ );
+
+ void CreateRoundedRectGeometry(
+ Geometry& geo,
+ Rect const& rect,
+ Vec2 const& radius
+ );
+
+ void CreateEllipseGeometry(
+ Geometry& geo,
+ Point const& center,
+ Vec2 const& radius
+ );
+
+ void CreatePathGeometrySink(
+ GeometrySink& sink
+ );
+
void DrawGeometry(
- ComPtr const& geometry,
+ Geometry const& geometry,
const Color& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);
void FillGeometry(
- ComPtr const& geometry,
+ Geometry const& geometry,
Color const& fill_color
);
void DrawRectangle(
Rect const& rect,
- const Color& stroke_color,
+ Color const& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);