update ActionPath
This commit is contained in:
parent
a1ade35331
commit
c5c0e1227e
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue