增加 export 命令
This commit is contained in:
88
SpineViewerCLI/Extension.cs
Normal file
88
SpineViewerCLI/Extension.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using SFML.Graphics;
|
||||
using SFML.System;
|
||||
using Spine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpineViewerCLI
|
||||
{
|
||||
public static class Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取一个对象副本, 继承所有状态
|
||||
/// </summary>
|
||||
public static SpineObject Copy(this SpineObject self, bool keepTrackTime = false)
|
||||
{
|
||||
var spineObject = new SpineObject(self, true);
|
||||
|
||||
// 拷贝轨道动画, 但是仅拷贝第一个条目
|
||||
foreach (var tr in self.AnimationState.IterTracks().Where(t => t is not null))
|
||||
{
|
||||
var t = spineObject.AnimationState.SetAnimation(tr!.TrackIndex, tr.Animation, tr.Loop);
|
||||
t.TimeScale = tr.TimeScale;
|
||||
t.Alpha = tr.Alpha;
|
||||
if (keepTrackTime)
|
||||
t.TrackTime = tr.TrackTime;
|
||||
}
|
||||
|
||||
// XXX(#105): 部分 3.4.02 版本模型在设置动画后出现附件残留, 因此强制进行一次 Setup
|
||||
if (spineObject.Version == SpineVersion.V34)
|
||||
{
|
||||
spineObject.Skeleton.SetSlotsToSetupPose();
|
||||
}
|
||||
|
||||
spineObject.Update(0);
|
||||
return spineObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前状态包围盒
|
||||
/// </summary>
|
||||
public static FloatRect GetCurrentBounds(this SpineObject self)
|
||||
{
|
||||
self.Skeleton.GetBounds(out var x, out var y, out var w, out var h);
|
||||
return new(x, y, Math.Max(w, 1e-6f), Math.Max(h, 1e-6f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算所有轨道第一个条目的动画时长最大值
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <returns></returns>
|
||||
public static float GetAnimationMaxDuration(this SpineObject self)
|
||||
{
|
||||
return self.AnimationState.IterTracks().Select(t => t?.Animation.Duration ?? 0).DefaultIfEmpty(0).Max();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合并另一个矩形
|
||||
/// </summary>
|
||||
public static FloatRect Union(this FloatRect self, FloatRect rect)
|
||||
{
|
||||
float left = Math.Min(self.Left, rect.Left);
|
||||
float top = Math.Min(self.Top, rect.Top);
|
||||
float right = Math.Max(self.Left + self.Width, rect.Left + rect.Width);
|
||||
float bottom = Math.Max(self.Top + self.Height, rect.Top + rect.Height);
|
||||
return new(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 按给定的帧率获取所有轨道第一个条目动画全时长包围盒大小, 是一个耗时操作, 如果可能的话最好缓存结果
|
||||
/// </summary>
|
||||
public static FloatRect GetAnimationBounds(this SpineObject self, float fps = 30)
|
||||
{
|
||||
using var copy = self.Copy();
|
||||
var bounds = copy.GetCurrentBounds();
|
||||
var maxDuration = copy.GetAnimationMaxDuration();
|
||||
for (float tick = 0, delta = 1 / fps; tick < maxDuration; tick += delta)
|
||||
{
|
||||
bounds = bounds.Union(copy.GetCurrentBounds());
|
||||
copy.Update(delta);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user