揭秘SKWarpGeometry

tl; dr :我构建了一个编辑器来使用本机SpriteKit扭曲图像

看起来像我所需要的,但是设置需要手动输入float2的数组-我实在太懒了,无法手动找出所有输入。
我需要一个小工具来调整输入,查看结果并导出。 听起来很简单…


要求

我希望能够加载图像,设置列和行,拉动控制点并将结果导出为Swift代码。


我打开了Xcode,并使用Game项目和SpriteKit&Swift创建了一个新的macOS项目。 我花了几个小时来整理所需的框架,使用NSSplitView和容器视图将视图控制器分离出来,第一个版本如下所示:

在这一点上,我可以加载磁盘映像,显示一个简单的检查器,并在时间轴上显示一个项目…。什么都没有用,因为它是伪造的,您无法选择图像上的黄色手柄,因此检查员的物品什么也没做。

但是我知道我必须证明移动控制点会扭曲精灵。

我在晚上和周末进行此操作,因此在短时间后,我可以拖动控制点并扭曲图像……它开始慢慢融合在一起。

我知道我希望能够单击控制手柄(黄色正方形)并四处移动,并查看精灵的变化。 考虑到这一点,我知道我必须拥有一个Inspector……就像在Xcode中一样,无论您选择什么,都可以拥有一个上下文相关的属性列表,您可以每周两次。
我还知道,通过阅读Apple文档,我可以按顺序应用任意数量的扭曲,因此我决定使用时间轴/图层系统。 同样,这应该是上下文相关的。
除此之外,我还知道整个场景可以具有列*行的任意组合,因此需要一个总体模型来存储它们,因此我填写了一个数据模型,如下所示:

文件模型
WarpModel
— — ControlPointModel

DocumentModel将存储:
*要使用的图片(实际上只是图片的URL)
*控制点的列数和行数。
*经层

WarpModel将存储
* ControlPoints列表

ControlPointModel将存储
*位置,简单的X,Y坐标

我希望我的工具能够保存我决定变形的任何图像的结构,因此我需要实现Swift 4的新Codable接口。 它非常易于使用,并且可以轻松地将数据编码和解码为JSON。

“很容易看到一个简单的想法如何变成许多功能”

然后,我需要(那里不存在很多)来证明我可以从一个几何图形动画到下一个几何图形。
那意味着必须有多层。 每个图层都有自己的一组控制点…但是我想在它们之间设置动画。 图层应具有不同的起点/终点。 如果它们同时启动,您将获得混合结果。

导出代码是应用程序最重要的功能,我不想只看到变形的结果,我需要将其导出并在另一个项目中使用。

每当我对数据进行更改时,该应用程序都会重新生成Swift代码,您可以根据需要复制/粘贴该代码。


选单

再一次,我发现自己要添加要素,在某些位置添加图层,如果您想随时间推移稍微移动控制点,则可以复制图层。
上下移动控制点,旋转控制点。

撤销重做
我不打算构建的另一个功能是撤消/重做,但这确实使您可以将代码结构化为可重用的组件。 我很高兴我做到了。

网格切换
在开发应用程序时,我发现我想像在回放模式下那样打开和关闭网格,或者在擦拭时间轴时希望看到结果,而不是网格使子画面模糊。 我还想查看经线与原始源图像的偏离程度,因此我添加了一个洋葱皮类型的功能,可以在其中看到原始图像,但是在需要时将其关闭

容器视图
容器视图允许您将视图控制器引用嵌入到另一个视图中,这可以使您分离视图。

时间线
时间轴由自定义绘制的NSTableColumn组成,我决定以100px的间隔绘制增量破折号,因为我决定将1秒锁定为100像素。 我不打算扩展时间轴,目前这不过是太过分了。

检验员
之前,我已经在我的应用程序中编写了检查器:Flux和Phonique,每次我编写一个时,我都是从头开始的,而且它们的实现越来越好,并且越来越快,前两次是用Objective-C编写的,这次我它是用Swift编写的,几乎感觉就像是自己编写的,实际上,这个应用程序的大部分都是这样。

行军蚁
我发现一个很酷的技巧是可以使用SKShapeNode和着色器来绘制行进的蚂蚁。

保存/加载,文件包装
macOS Apps允许您保存/加载文件,但我不想只保存一个简单的JSON文件。
文件包装器允许您创建目录类型的结构并存储多个文件。 因此,对于WarpTool,我存储了数据的JSON文件以及QuickLook缩略图。 这意味着保存文件后,我将截取设计区域的屏幕截图。 将其另存为QuickLook缩略图,然后macOS足够智能,可以将该图像显示为文件的图标。

演示/模型分离
我认为这是实践带来的,而不是其他任何事情,关注点分离是一个非常好的主意,例如:

该应用程序的主要设计区域是SpriteKit视图,因此我处理SKNodes / SKSpriteNodes等。
我有一个DocumentModel,它的工作是跟踪Image,WarpLayers,行数和列数等。
我可以做到这一点,以便在更新图像时,也可以为原始图像更新SKSpriteNode,…..但是最终您到了一个点,就是有些东西完全被数据与屏幕上的外观纠缠在一起。
因此,我将模型分为模型/演示文稿。 我有DocumentModel,还有DocumentNode。 DocumentNode管理DocumentModel的所有图形。 这也意味着,如果我决定改用SceneKit,则可以为SceneKit添加一个演示文稿,并根据需要交换它们的位置,而不会影响模型。

KVC /观察/ NS
键值编码是使应用成为可能的粘合剂,通过使用NS类…NSNumber,您可以观察属性的变化。 我尝试观察像Bool / Float这样的原始类型,但没有任何乐趣。 如果您还没有玩过KVC,那就去做吧! 这很棒!

相机
我正在使用SKCameraNode通过一些填充调整所选图像上的设计视图。 如果您花时间在上面,可以做很多事情,例如缩放,平移,但是我只是想要一些可以起作用的东西。

加载图像后,获得尺寸,计算高度/宽度的最大值,然后设置相机的比例。

 让minimum = min(imageFrame.size.height,imageFrame.size.width)+填充 

让scale = min(physicalFrame.size.width / minimum,physicalFrame.size.height / minimum)cameraNode.setScale(1 / scale)

模式
该应用程序具有四种模式,“设计”,“动画”,“擦洗”,“物理”。 该应用一次只能处于一种状态。
* 设计模式是您可以编辑手柄的地方
* 动画模式通过SpriteKit的SKAction.warp方法运行WarpLayers。
* 擦洗模式是动画和设计的混合。 给定时间轴上的一点,我能够计算要使用的WarpModels并在其中插入WarpGrids。

  func lerp(_ x:浮点,_ a:浮点,_ b:浮点)->浮点{返回a *(1.0-x)+ b * x 
}
  • 仅出于娱乐目的而实施的物理模式将SpriteKit世界的物理速度设置为0到1。非常简单。

UI设计
我使设计尽可能简单,并尽可能减少设计。 它应该是加载,执行所需操作,获取输出并关闭它的快速工具。


即时串流

作为脚注比什么都重要,我在这里阅读了Noopkat实时流媒体课程,我想我会早点给它。
起初,我只是流媒体屏幕,没有视频,也没有麦克风。 然后我打开麦克风,感觉就像一个不同的世界。 突然之间,我不得不开始谈论手头的问题,思考如何解决该问题。 确实让我考虑了我正在做的事情,我建议这样做。
但是,由于弄乱了配置,我最终还是删除了我的视频,这些视频难以辨认。 如果有人想看到我再试一次,请告诉我!

虫子
是的,我敢肯定我有错误,该应用程序的创建只是为了证明一个观点,如果您发现一个问题,则可以得到10点!


预测

我不认为SpriteKit会得到足够的爱,我喜欢它,当然还有bug,但是使用SpriteKit可以使您这么快地启动并运行! 我认为Apple会很快对SpriteKit编辑器进行改造,也许包括这样的功能,甚至可能更强大,包括骨骼和自动几何生成。

结论

很容易被带走。 我想做的就是证明SpriteKit是否可以做我想做的事情,而且肯定可以。

您可以在Twitter上关注我/通过Twitter与我联系:https://twitter.com/nthState或在我的网站上查看我的所作所为:www.chrisdavis.com

谢谢阅读!