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
: public ActionGroup
@ -100,4 +103,7 @@ namespace kiwano
virtual ~ActionSpawn() {}
};
#pragma warning(pop)
}

View File

@ -424,36 +424,84 @@ namespace kiwano
// 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)
, start_(start)
, end_(end)
, geo_(geo)
, rotating_(rotating)
, path_beginning_(false)
, geo_(nullptr)
, geo_sink_(nullptr)
{
}
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
{
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)
{
start_pos_ = target->GetPosition();
if (path_beginning_)
{
EndPath();
}
if (!geo_)
{
Complete(target);
}
}
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;
if (geo_->ComputePointAt(length, &point, &tangent))
if (ComputePointAtLength(length, &point, &tangent))
{
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

View File

@ -20,8 +20,8 @@
#pragma once
#include "Action.h"
#include "Geometry.h" // ActionPath
#include "../base/logs.h"
#include "../renderer/render.h" // ID2D1PathGeometry, ID2D1GeometrySink
namespace kiwano
{
@ -419,7 +419,6 @@ namespace kiwano
public:
ActionPath(
Duration duration, /* 持续时长 */
GeometryPtr geo, /* 섯부暠近 */
bool rotating = false, /* 沿路径切线方向旋转 */
float start = 0.f, /* 起点 */
float end = 1.f, /* 终点 */
@ -432,17 +431,69 @@ namespace kiwano
// 获取该动作的倒转
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:
void Init(NodePtr target) override;
void UpdateTween(NodePtr target, float percent) override;
protected:
bool rotating_;
float start_;
float end_;
Point start_pos_;
GeometryPtr geo_;
bool path_beginning_;
bool rotating_;
float start_;
float end_;
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)
{
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)
{
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)
{
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)
{
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.
inline float ConvertDipsToPixels(float dips, float dpi)
{