update ActionPath

This commit is contained in:
Nomango 2019-08-08 13:46:14 +08:00
parent a1ade35331
commit c5c0e1227e
4 changed files with 313 additions and 17 deletions

View File

@ -72,6 +72,9 @@ namespace kiwano
}; };
#pragma warning(push)
#pragma warning(disable : 4996)
// 顺序动作 // 顺序动作
class KGE_API ActionSequence class KGE_API ActionSequence
: public ActionGroup : public ActionGroup
@ -100,4 +103,7 @@ namespace kiwano
virtual ~ActionSpawn() {} virtual ~ActionSpawn() {}
}; };
#pragma warning(pop)
} }

View File

@ -424,36 +424,84 @@ namespace kiwano
// ActionPath // ActionPath
//------------------------------------------------------- //-------------------------------------------------------
ActionPath::ActionPath(Duration duration, GeometryPtr geo, bool rotating, float start, float end, EaseFunc func) ActionPath::ActionPath(Duration duration, bool rotating, float start, float end, EaseFunc func)
: ActionTween(duration, func) : ActionTween(duration, func)
, start_(start) , start_(start)
, end_(end) , end_(end)
, geo_(geo)
, rotating_(rotating) , rotating_(rotating)
, path_beginning_(false)
, geo_(nullptr)
, geo_sink_(nullptr)
{ {
} }
ActionPtr ActionPath::Clone() const ActionPtr ActionPath::Clone() const
{ {
return new ActionPath(dur_, geo_, rotating_, start_, end_, ease_func_); ActionPathPtr clone = new ActionPath(dur_, rotating_, start_, end_, ease_func_);
if (clone)
{
clone->SetGeometry(geo_);
}
return clone;
} }
ActionPtr ActionPath::Reverse() const ActionPtr ActionPath::Reverse() const
{ {
return new ActionPath(dur_, geo_, rotating_, end_, start_, ease_func_); 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(NodePtr target) void ActionPath::Init(NodePtr target)
{ {
start_pos_ = target->GetPosition(); start_pos_ = target->GetPosition();
if (path_beginning_)
{
EndPath();
}
if (!geo_)
{
Complete(target);
}
} }
void ActionPath::UpdateTween(NodePtr target, float percent) void ActionPath::UpdateTween(NodePtr target, float percent)
{ {
float length = geo_->GetLength() * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f); float length = GetPathLength() * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f);
Point point, tangent; Point point, tangent;
if (geo_->ComputePointAt(length, &point, &tangent)) if (ComputePointAtLength(length, &point, &tangent))
{ {
target->SetPosition(start_pos_ + point); target->SetPosition(start_pos_ + point);
@ -466,6 +514,123 @@ namespace kiwano
} }
} }
void ActionPath::BeginPath()
{
if (path_beginning_) return;
path_beginning_ = true;
geo_ = nullptr;
geo_sink_ = nullptr;
auto factory = Renderer::Instance()->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(Array<Point> const& points)
{
if (!path_beginning_)
{
BeginPath();
}
if (geo_sink_ && !points.empty())
{
geo_sink_->AddLines(
reinterpret_cast<const D2D_POINT_2F*>(&points[0]),
static_cast<UINT32>(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 // ActionCustom

View File

@ -20,8 +20,8 @@
#pragma once #pragma once
#include "Action.h" #include "Action.h"
#include "Geometry.h" // ActionPath
#include "../base/logs.h" #include "../base/logs.h"
#include "../renderer/render.h" // ID2D1PathGeometry, ID2D1GeometrySink
namespace kiwano namespace kiwano
{ {
@ -419,7 +419,6 @@ namespace kiwano
public: public:
ActionPath( ActionPath(
Duration duration, /* 持续时长 */ Duration duration, /* 持续时长 */
GeometryPtr geo, /* 섯부暠近 */
bool rotating = false, /* 沿路径切线方向旋转 */ bool rotating = false, /* 沿路径切线方向旋转 */
float start = 0.f, /* 起点 */ float start = 0.f, /* 起点 */
float end = 1.f, /* 终点 */ float end = 1.f, /* 终点 */
@ -432,17 +431,69 @@ namespace kiwano
// 获取该动作的倒转 // 获取该动作的倒转
ActionPtr Reverse() const override; ActionPtr Reverse() const override;
// 开始添加路径
void BeginPath();
// 结束路径
void EndPath(
bool closed = false /* 路径是否闭合 */
);
// 添加一条线段
void AddLine(
Point const& point /* 端点 */
);
// 添加多条线段
void AddLines(
Array<Point> 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<ID2D1PathGeometry> GetGeometry() const { return geo_; }
// 设置几何路径
inline void SetGeometry(ComPtr<ID2D1PathGeometry> geo) { geo_ = geo; }
protected: protected:
void Init(NodePtr target) override; void Init(NodePtr target) override;
void UpdateTween(NodePtr target, float percent) override; void UpdateTween(NodePtr target, float percent) override;
protected: protected:
bool rotating_; bool path_beginning_;
float start_; bool rotating_;
float end_; float start_;
Point start_pos_; float end_;
GeometryPtr geo_; Point start_pos_;
ComPtr<ID2D1PathGeometry> geo_;
ComPtr<ID2D1GeometrySink> geo_sink_;
}; };

View File

@ -38,36 +38,110 @@ namespace kiwano
} }
} }
inline D2D1_POINT_2F const& ConvertToPoint2F(Vec2 const& point) //
// Point2F
//
inline D2D1_POINT_2F const& ConvertToPoint2F(Vec2 const& vec2)
{ {
return reinterpret_cast<D2D1_POINT_2F const&>(point); return reinterpret_cast<D2D1_POINT_2F const&>(vec2);
} }
inline D2D1_SIZE_F const& ConvertToSizeF(Vec2 const& size) inline D2D1_POINT_2F& ConvertToPoint2F(Vec2& vec2)
{ {
return reinterpret_cast<D2D1_SIZE_F const&>(size); return reinterpret_cast<D2D1_POINT_2F&>(vec2);
} }
inline const D2D1_POINT_2F* ConvertToPoint2F(const Vec2* vec2)
{
return reinterpret_cast<const D2D1_POINT_2F*>(vec2);
}
inline D2D1_POINT_2F* ConvertToPoint2F(Vec2* vec2)
{
return reinterpret_cast<D2D1_POINT_2F*>(vec2);
}
//
// SizeF
//
inline D2D1_SIZE_F const& ConvertToSizeF(Vec2 const& vec2)
{
return reinterpret_cast<D2D1_SIZE_F const&>(vec2);
}
inline D2D1_SIZE_F& ConvertToSizeF(Vec2& vec2)
{
return reinterpret_cast<D2D1_SIZE_F&>(vec2);
}
inline const D2D1_SIZE_F* ConvertToSizeF(const Vec2* vec2)
{
return reinterpret_cast<const D2D1_SIZE_F*>(vec2);
}
inline D2D1_SIZE_F* ConvertToSizeF(Vec2* vec2)
{
return reinterpret_cast<D2D1_SIZE_F*>(vec2);
}
//
// SizeF
//
inline D2D1_RECT_F ConvertToRectF(Rect const& rect) inline D2D1_RECT_F ConvertToRectF(Rect const& rect)
{ {
return D2D1_RECT_F{ rect.origin.x, rect.origin.y, rect.origin.x + rect.size.x, rect.origin.y + rect.size.y }; return D2D1_RECT_F{ rect.origin.x, rect.origin.y, rect.origin.x + rect.size.x, rect.origin.y + rect.size.y };
} }
//
// SizeF
//
inline D2D1_COLOR_F const& ConvertToColorF(Color const& color) inline D2D1_COLOR_F const& ConvertToColorF(Color const& color)
{ {
return reinterpret_cast<D2D1_COLOR_F const&>(color); return reinterpret_cast<D2D1_COLOR_F const&>(color);
} }
inline D2D1_COLOR_F& ConvertToColorF(Color& color)
{
return reinterpret_cast<D2D1_COLOR_F&>(color);
}
inline const D2D1_COLOR_F* ConvertToColorF(const Color* color)
{
return reinterpret_cast<const D2D1_COLOR_F*>(color);
}
inline D2D1_COLOR_F* ConvertToColorF(Color* color)
{
return reinterpret_cast<D2D1_COLOR_F*>(color);
}
//
// SizeF
//
inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix const& matrix) inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(Matrix const& matrix)
{ {
return reinterpret_cast<D2D1_MATRIX_3X2_F const&>(matrix); return reinterpret_cast<D2D1_MATRIX_3X2_F const&>(matrix);
} }
inline D2D1_MATRIX_3X2_F& ConvertToMatrix3x2F(Matrix& matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F&>(matrix);
}
inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix* matrix) inline const D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(const Matrix* matrix)
{ {
return reinterpret_cast<const D2D1_MATRIX_3X2_F*>(matrix); return reinterpret_cast<const D2D1_MATRIX_3X2_F*>(matrix);
} }
inline D2D1_MATRIX_3X2_F* ConvertToMatrix3x2F(Matrix* matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F*>(matrix);
}
// Converts a length in device-independent pixels (DIPs) to a length in physical pixels. // Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
inline float ConvertDipsToPixels(float dips, float dpi) inline float ConvertDipsToPixels(float dips, float dpi)
{ {